home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / m2 / cat3src / cat / parser.i < prev    next >
Text File  |  1997-10-26  |  91KB  |  2,387 lines

  1. IMPLEMENTATION MODULE Parser;
  2.  
  3. (*==============================================================*
  4.  * Modul:               CAT-Outfile Parser, neue Version        *
  5.  * Autor:               Johannes G”ttker-Schnetmann             *
  6.  * erstellt am:         09.03.1992                              *
  7.  * letzte Žnderung am:  29.12.1992                              *
  8.  * Version:             1.0                                     *
  9.  * Interne Version:     V#0005                                  *
  10.  *==============================================================*
  11.  
  12.   Kleinere Problemchen:
  13.  -   Wenn w„hrend der Sortierungsphase ab der zweiten neuen Gruppe etwas
  14.      schief l„uft, dann sind diese Gruppen frderhin als dummy in der Liste,
  15.      bis zum ersten Mal doch noch etwas in sie eingefgt wird.
  16.  
  17.  - Array mit der Verkettungsinformationen noch statisch in diesem Modul
  18.    deklariert, das muž noch dynamisch werden
  19.  
  20.  - Die Strings in InsertPersonal sind noch etwas ppig angegeben..
  21.  
  22.  - Das Logfile darf nicht behandelt werden, wenn alle Nachrichten von 
  23.    der Datenbank abgelehnt wurden.
  24.  
  25.  *---------------------------------------------------------------------------
  26.  * Datum    Vers. Autor  Žnderung (Arbeitsbericht)                            
  27.  *---------------------------------------------------------------------------
  28.  * 09.03.92 0001  JGS    Erste Version
  29.  * 10.03.92 0002  JGS    Implementation .. -12./18.-20./22.
  30.  * 24.03.92       JGS    Testen und Fehlerkorrigieren 25./
  31.  * 26.03.92 0003  JGS    Maus-Logfile-Behandlung
  32.  * 15.04.92 0004  JGS    Anpassung an WatchDog und Dupecheck
  33.  * 16.04.92       JGS    Verbesserte Logdatei
  34.  * 24.05.92       JGS    leere InfoFiles korrekt/Positionen sichern/Files schliežen
  35.  * 27.12.92 0005  JGS    nach einigen Žnderungen, die hier nicht aufgefhrt sind..
  36.  *                       jetzt Gesamtstatistik eingebaut.
  37.  * 12.08.93       JGS    Username kann ber die Variable 'Username' gesetzt werden
  38.  *---------------------------------------------------------------------------
  39.  *)
  40. FROM SYSTEM          IMPORT ADR, ADDRESS, CALLSYS, CADR, ASSEMBLER;
  41.  
  42. (* Megamax-spezifische Module *)
  43. FROM Characters      IMPORT CR, LF;
  44. IMPORT BinOps;
  45. IMPORT Block;
  46. IMPORT StrConv;
  47. IMPORT Strings;
  48.  
  49. (* MagicLib *)
  50. IMPORT MagicAES;
  51. IMPORT MagicDOS;
  52. IMPORT MagicStrings;
  53. IMPORT MagicCookie;
  54.  
  55. (* MagicTools *)
  56. IMPORT mtDir;
  57. IMPORT mtAppl;
  58. IMPORT mtAlerts;
  59. IMPORT mtTextfiles;
  60.  
  61. (* Cat-Module *)
  62. FROM MTPaths         IMPORT ImportPath, ARCPath, ARCName, DataPath,
  63.                             MessagePath, archiveName;
  64. FROM UserInformation IMPORT UserBLK, batchProcess;
  65. FROM Void            IMPORT v;
  66. FROM Infofiles       IMPORT LoadInfoInf, SaveInfoInf, SetInfoCrc, IsInfoFile,
  67.                             TestDirectParse;
  68. IMPORT ARCStarter;
  69. IMPORT showImport;
  70. IMPORT CatTypes;
  71. IMPORT CatFiles;
  72. IMPORT CatLog;
  73. IMPORT CatGlobal;
  74. IMPORT data;
  75. IMPORT dataSys;
  76. IMPORT MTE;
  77. IMPORT Protokoll;
  78. IMPORT Messages;
  79. IMPORT ConfVars;
  80. IMPORT Varnames;
  81. IMPORT VDIStandards;
  82. IMPORT WdwManager;
  83. IMPORT GroupSelect;
  84. IMPORT IoFilter;
  85. IMPORT handlePool;
  86. IMPORT CatHelp;
  87.  
  88. (* IMPORT Debug; (* $D+*) *)
  89.  
  90. (* Konstanten fr LOGFILE-Ausgabe *)
  91.  
  92. CONST
  93.       cSpace9Str  = '         ';
  94.       cMessStr    = ' Nachricht';
  95.       cExtStr     = 'en';
  96.       cWarStr     = ' war';
  97.       cDbStr      = ' vom Datenbankmodul und ';
  98.       cWdogStr    = ' vom WatchDog abgelehnt. ';
  99.       cImpStr     = ' importiert.';
  100.       cGroupChange= 'Gruppenwechsel zu ';
  101.       cPrivate    = 'Private Messages';
  102.       cSysop      = 'SYSOP ';
  103.  
  104.       cOfNdel     = 'Outfile-Text konnte nicht gel”scht werden';
  105.       cOfDel      = 'Outfile-Text gel”scht';
  106.       
  107.       cUnknown    = 'Unbekannter Eintrag: ';
  108.     
  109. CONST minSpace    = LONG(MAX(INTEGER)); (* Mindestgr”že Outfile-Puffers    *)
  110.       secureBytes = LONG(MAX(INTEGER)); (* Platz, der auf Einfgelaufwerk  *)
  111.                                         (* zus„tzlich zur L„nge des        *)
  112.                                         (* Outfiles noch vorhanden sein    *)
  113.                                         (* muž                             *)
  114.       infoFileBuffer = 32*1024;         (* Puffergr”že fr Textfiles       *)
  115.       logFileBuffer  = 16*1024;
  116.       errFileBuffer  = 4*1024;
  117.       datFileBuffer  = 4*1024;
  118.  
  119.       sixteenKB      = 64*1024 - 256;     (* Das ist die maximale messagel„nge, 
  120.                                            * die wir akzeptieren 
  121.                                            *)
  122.  
  123.       OutfileTxt  = "outfile.txt"; (* Muž noch einstellbar werden!         *)
  124.       LogFile     = 'LOG.txt';
  125.       HeadFile    = 'HEAD.txt';
  126.       ErrFile     = 'protokol.txt';
  127.       notDeleted  = ' nicht gel”scht';
  128.  
  129.       isDupe      = 'Dupe zu';
  130.       refNotFound = 'Mitteilung * nicht gefunden';
  131.   
  132.  
  133.       spaceForOwnMess = 99;   (* Platz der bei der Behandlung des Logfiles   *)
  134.                               (* fr eigene Messages zu reservieren versucht *)
  135.                               (* wird.                                       *)
  136.       
  137. TYPE NrTypes = (LOG, REN, CMD, HEAD, mKOM, mNEW, mPER, mANS, normal, nottich);
  138.  
  139. (* Beim Einlagern wird jetzt schon versucht, die Gruppenliste in data zu   *)
  140. (* erweitern. Klappt dies nicht, dann wird das Einfgen abgebrochen!       *)
  141.  
  142. (*
  143. Idee:
  144. Es wird ein kleines Array fr die Verkettungsinformation auf dem Stack
  145. angelegt, dann werden cardinals fr die Verkettung benutzt, denn das
  146. verbraucht weniger Platz und ist evtl. schneller. Das Array fažt demn„chst
  147. vielleicht so etwa 1000 Msgs, fr die Testphase erheblich weniger, d.h. so
  148. 50 bis 100. Das Outfile wird in zwei Schleifen bearbeitet. In der „užeren
  149. wird es h„ppchenweise in den Speicher geladen und in der inneren
  150. durchgesehen, bis das Verkettungsarray voll ist. d.h. Die innere Schleife
  151. arbeitet den Block im Speicher ab.
  152. *)
  153.  
  154. CONST EndOfList = 0FFFFH;
  155.       maxArray  = 1000; (* Maximale Anzahl an Positionen pro Array *)
  156.       maxGroup  = 1023;
  157.       
  158. TYPE onePosItem = RECORD
  159.                     next   : CARDINAL;
  160.                     offset : LONGCARD
  161.                   END;
  162. TYPE onePosArrayPtr = POINTER TO onePosArray;
  163. TYPE onePosArray = ARRAY[0..maxArray] OF onePosItem;
  164. TYPE oneMaxArray = ARRAY[0..maxGroup] OF CARDINAL;
  165. TYPE oneGroupSet = SET OF [0..maxGroup];
  166.  
  167. (* es wird ein Array der Startpositionen und eins mit den aktuellen
  168.  * Endwerten der einzelnen Gruppenlisten und ein Array mit der Verwaltungs-
  169.  * information verwaltet. Wenn eine neue Nachricht an eine Gruppenliste
  170.  * angeh„ngt werden soll, so muž zun„chst in dem Array mit den Start-
  171.  * positionen nachgesehen werden, ob noch kein Eintrag erfolgte. Anschliežend
  172.  * wird im letzten Element dieser Gruppe, das an der Position gMax[gruppe]
  173.  * steht, der neue Eintrag verkettet
  174. *)
  175.  
  176. VAR maxOver : BOOLEAN;      (* Maximalgr”že berschritten? *)
  177.     filteredToRead: BOOLEAN;    (* Gefilterte auf Gelesen setzen? *)
  178.     firstLog: BOOLEAN;          (* Erstes Logfile schon erstellt *)
  179.     headThere: BOOLEAN;         (* #HEAD ist gekommen *)
  180.     groupsUsed: oneGroupSet;
  181.     redrawCheck: INTEGER;
  182.  
  183.     (*
  184.     useLongIds: BOOLEAN;        (* Lange IDs fr Nachrichten verwenden 
  185.                                  *)
  186.     *)
  187.  
  188. (* Arrays mit der Verkettungsinformation, demn„chst dynamisch, s.o. *)
  189. VAR s, m : oneMaxArray; 
  190.     g    : onePosArray; (* Demn„chst anfordern *)
  191.  
  192. PROCEDURE typeOf(VAR str : ARRAY OF CHAR):NrTypes;
  193. BEGIN
  194.   IF str[0] = 0C THEN RETURN nottich
  195.   (*
  196.   ELSIF (str[0]='C') & (str[1]='M') & (str[2]='D') THEN RETURN CMD
  197.   *)
  198.   ELSIF (str[0]='L') & (str[1]='O') & (str[2]='G') THEN RETURN LOG
  199.   ELSIF (str[0]='R') & (str[1]='E') & (str[2]='N') THEN RETURN REN
  200.   ELSIF (str[0]='H') & (str[1]='E') & (str[2]='A') & (str[3]='D') THEN RETURN HEAD
  201.   (*
  202.   ELSIF (str[0]='K') & (str[1]='O') & (str[2]='M') THEN RETURN mKOM
  203.   ELSIF (str[0]='N') & (str[1]='E') & (str[2]='W') THEN RETURN mNEW
  204.   ELSIF (str[0]='P') & (str[1]='E') & (str[2]='R') THEN RETURN mPER
  205.   ELSIF (str[0]='A') & (str[1]='N') & (str[2]='S') THEN RETURN mANS
  206.   *)
  207.   ELSE RETURN normal END
  208. END typeOf;
  209.  
  210. PROCEDURE isOneInf(VAR str   : ARRAY OF CHAR; VAR infLen: INTEGER):BOOLEAN;
  211.   VAR p : CARDINAL;
  212.       infName: ARRAY [0..8] OF CHAR;
  213. BEGIN
  214.   (*
  215.   IF (str[0] = 'I') OR (str[0] = 'J') THEN
  216.   *)
  217.   p := 0;
  218.   WHILE (str[p] > ' ') & (str[p] # '@') & (p <= 8) DO 
  219.     infName[p] := str[p];
  220.     INC (p) 
  221.   END;
  222.   IF (str[p] # '@') & (p <= 8) THEN 
  223.     infName [p] := '';
  224.     infLen := p;
  225.     RETURN IsInfoFile (infName, TRUE);
  226.   END;
  227.   RETURN FALSE
  228.   (*
  229.   END;
  230.   RETURN FALSE
  231.   *)
  232. END isOneInf;
  233.  
  234. PROCEDURE isUnknownInf(VAR str   : ARRAY OF CHAR; VAR infLen: INTEGER):BOOLEAN;
  235.   VAR p : CARDINAL;
  236. BEGIN
  237.   p := 0;
  238.   WHILE (str[p] > ' ') & (str[p] # '@') & (p <= 8) DO 
  239.     INC (p) 
  240.   END;
  241.   IF (str[p] # '@') & (p <= 8) THEN 
  242.     infLen := p;
  243.     RETURN TRUE;
  244.   END;
  245.   RETURN FALSE
  246. END isUnknownInf;
  247.  
  248. PROCEDURE OpenTextFile(REF path,
  249.                            name : ARRAY OF CHAR;
  250.                            mode : mtTextfiles.Textmode;
  251.                            buff : CARDINAL;
  252.                        VAR file : mtTextfiles.TEXTFILE):BOOLEAN;
  253. VAR scrap : CatTypes.pathStrType;
  254. BEGIN
  255.   MagicStrings.Assign(path, scrap);
  256.   MagicStrings.Append(name, scrap);
  257.   RETURN mtTextfiles.OpenTextfile(scrap, mode, buff, file) OR
  258.          mtTextfiles.OpenTextfile(scrap, mode, 1, file);
  259.          (* Falls kein Speicher mehr frei *)
  260. END OpenTextFile;
  261.  
  262. (*- Logfile behandeln -----------------------------------------------------*)
  263.  
  264. PROCEDURE processLog();
  265. VAR idScrap : CatTypes.String255;
  266.     shortId,
  267.     mscrap,
  268.     scrap   : CatTypes.String255; (* Fr die Modi nach '#' und '"' *)
  269.     type    : CHAR;
  270.     key     : CHAR;
  271.     log     : mtTextfiles.TEXTFILE;
  272.     err     : mtTextfiles.TEXTFILE; (* Fehlermeldungen u.„. *)
  273.     errOpen : BOOLEAN;
  274.     refAssigned,
  275.     refMess : BOOLEAN;
  276.     find    : CARDINAL;
  277.     find2   : CARDINAL;
  278.     writeInf: BOOLEAN;
  279.     datOpen : BOOLEAN;
  280.     dat     : data.OneGroupHandle;
  281.     gotId   : BOOLEAN;
  282.     abort   : BOOLEAN;
  283.     readNew : BOOLEAN;
  284.     anz,
  285.     anz2,
  286.     not2,
  287.     not     : CARDINAL; (* WatchDog und defekte gibt's hier nicht. *)
  288.  
  289.  
  290.   PROCEDURE OpenPers (): BOOLEAN;
  291.   BEGIN
  292.     IF ~datOpen THEN
  293.       IF anz = 0
  294.       THEN
  295.         CatLog.WriteLn();
  296.         CatLog.WriteStringNTime(cGroupChange);
  297.         CatLog.WriteLine(cPrivate);
  298.       END;
  299.       datOpen := data.OpenOneGroup(dataSys.private, spaceForOwnMess, TRUE, dat);
  300.       IF ~datOpen THEN
  301.         RETURN FALSE
  302.       END;
  303.     END;
  304.     RETURN TRUE;
  305.   END OpenPers;
  306.  
  307.   PROCEDURE WriteDat(VAR mess : data.PtrRecord; VAR abort : BOOLEAN):BOOLEAN;
  308.     VAR isDupe: BOOLEAN;
  309.         succ  : BOOLEAN;
  310.   BEGIN
  311.     IF ~OpenPers() THEN RETURN FALSE END;
  312.     IF datOpen THEN
  313.       succ := data.AppendMessage(dat, data.own, {}, mess, v.bool, v.bool, isDupe, abort);
  314.       IF ~succ
  315.       THEN
  316.         (* Eigener Dupe, kommt durch :PE *)
  317.         IF isDupe THEN RETURN TRUE END;
  318.       END;
  319.       RETURN succ;
  320.     END;
  321.     RETURN FALSE; 
  322.   END WriteDat;
  323.  
  324.   PROCEDURE CloseDat(VAR abort : BOOLEAN; newMsgs : CARDINAL);
  325.   BEGIN
  326.     IF datOpen THEN
  327.       data.CloseOneWriteGroup(dat, newMsgs, ~abort, abort);
  328.       datOpen := FALSE;
  329.     END;
  330.   END CloseDat;
  331.  
  332.   PROCEDURE ErrorWrite(REF str : ARRAY OF CHAR);
  333.   BEGIN
  334.     IF ~errOpen THEN
  335.       errOpen := OpenTextFile(DataPath, ErrFile, mtTextfiles.WRITE, errFileBuffer, err);
  336.     END;
  337.     IF errOpen THEN
  338.       mtTextfiles.WriteLine(err, str);
  339.     END;
  340.   END ErrorWrite;
  341.  
  342.   PROCEDURE ErrorLn();
  343.   BEGIN
  344.     IF errOpen THEN
  345.       mtTextfiles.WriteLn(err);
  346.     END;
  347.   END ErrorLn;
  348.   
  349.   PROCEDURE ErrorClose();
  350.   BEGIN
  351.     IF errOpen THEN
  352.       mtTextfiles.CloseTextfile(err);
  353.     END;
  354.   END ErrorClose;
  355.  
  356.   PROCEDURE DeleteThem(REF path, name, ext : ARRAY OF CHAR);
  357.   VAR nameScrap : CatTypes.nameStrType;
  358.   BEGIN
  359.     MagicStrings.Assign(name, nameScrap);
  360.     MagicStrings.Append(ext, nameScrap);
  361.     IF ~CatFiles.DeleteFile(path, nameScrap) THEN
  362.       ErrorWrite(nameScrap);
  363.       ErrorWrite(' konnte nicht gel”scht werden.');
  364.       ErrorLn();
  365.     END;
  366.   END DeleteThem;
  367.  
  368.   PROCEDURE InsertPersonal(VAR id, longId, name : ARRAY OF CHAR);
  369.   VAR nameScrap : CatTypes.nameStrType;
  370.       theFile   : mtTextfiles.TEXTFILE;
  371.       mess      : data.PtrRecord;
  372.       refId,
  373.       rId,
  374.       to,
  375.       wegen, 
  376.       EZeile    : CatTypes.Str1023Ptr;
  377.       (*
  378.       str      : ARRAY[0..3] OF CatTypes.String255;
  379.       *)
  380.       z        : CARDINAL;
  381.  
  382.     PROCEDURE OpenFile(REF ext : ARRAY OF CHAR):BOOLEAN;
  383.     BEGIN
  384.       MagicStrings.Assign(name, nameScrap);
  385.       MagicStrings.Append(ext, nameScrap);
  386.       IF ~OpenTextFile(MessagePath,
  387.                        nameScrap,
  388.                        mtTextfiles.READ,
  389.                        datFileBuffer,
  390.                        theFile)
  391.       THEN
  392.         ErrorWrite('Folgende Datei konnte nicht ge”ffnet werden:');
  393.         ErrorLn();
  394.         ErrorWrite(nameScrap);
  395.         ErrorLn();
  396.         RETURN FALSE
  397.       END;
  398.       RETURN TRUE
  399.     END OpenFile;
  400.  
  401.   BEGIN
  402.     (* Jetzt normal bearbeiten *)
  403.     INC(anz); (* Wieder ein Schreibversuch.. *)
  404.     INC(anz2); (* Wieder ein Schreibversuch.. *)
  405.     IF LENGTH(name) > 10 THEN 
  406.       INC(not); (* Diese Msg wurde nicht angenommen *)
  407.       INC(not2); (* Diese Msg wurde nicht angenommen *)
  408.       ErrorWrite('Name zu lang: ');
  409.       ErrorWrite(name);
  410.       ErrorLn();
  411.     ELSE
  412.       mess.whatsThere := data.stringSet{data.bId, data.bTextDatei};
  413.       mess.pId := ADR(id);
  414.       Messages.GetHdrInfos (mscrap, refId, to, wegen, EZeile, rId);
  415.       IF (refId # NIL) & (refId^[0] # '')
  416.       THEN
  417.         INCL(mess.whatsThere, data.bRefNr);
  418.         mess.pRefNr := ADDRESS(refId);
  419.       END;
  420.       IF (rId # NIL) & (rId^[0] # '')
  421.       THEN
  422.         INCL(mess.whatsThere, data.bRId);
  423.         mess.pRId := ADDRESS(rId);
  424.       END;
  425.       IF (to # NIL) & (to^[0] # '')
  426.       THEN
  427.         INCL(mess.whatsThere, data.bAn);
  428.         mess.pAn := ADDRESS(to);
  429.       END;
  430.       IF (wegen # NIL) & (wegen^[0] # '')
  431.       THEN
  432.         INCL(mess.whatsThere, data.bWegen);
  433.         mess.pWegen := ADDRESS(wegen);
  434.       END;
  435.       IF (EZeile # NIL) & (EZeile^[0] # '')
  436.       THEN
  437.         INCL(mess.whatsThere, data.bEZeit);
  438.         mess.pEZeit := ADDRESS(EZeile);
  439.       END;
  440.       IF (LENGTH (longId) > 0)
  441.       THEN
  442.         INCL(mess.whatsThere, data.bMId);
  443.         mess.pMId := ADR (longId);
  444.       END;
  445.       IF OpenFile(CatTypes.textExt) THEN (* sonst wurde gemeckert *)
  446.         mess.txt := theFile;
  447.         IF abort OR ~WriteDat(mess, abort) THEN (* Nur einmal versuchen! *)
  448.           ErrorWrite('Die Datenbank hat die Nachricht ');
  449.           ErrorWrite(id);
  450.           ErrorWrite(' nicht angenommen');
  451.           ErrorLn();
  452.           INC(not);
  453.           INC(not2);
  454.         END;
  455.         mtTextfiles.CloseTextfile(theFile);
  456.         IF anz2-not2 >= spaceForOwnMess
  457.         THEN
  458.           (* Platz fr neue Nachrichten voll, DB schliežen und dann wieder ”ffnen 
  459.            *)
  460.           CloseDat (abort, anz2-not2);
  461.           anz2 := 0;
  462.           not2 := 0;
  463.         END;
  464.       END;
  465.     END;
  466.   END InsertPersonal;
  467.  
  468.   PROCEDURE Is (VAR refStr : ARRAY OF CHAR; REF testStr : ARRAY OF CHAR): BOOLEAN;
  469.     VAR l : CARDINAL;
  470.         res : BOOLEAN;
  471.   BEGIN
  472.     l := MagicStrings.Length (refStr);
  473.     res := MagicStrings.Pos (testStr, refStr, 0, TRUE) < l;
  474.     RETURN res;
  475.   END Is;
  476.   
  477.   PROCEDURE checkHeadLine (line: ARRAY OF CHAR);
  478.     VAR key : CHAR;
  479.         mscrap  : CatTypes.String255;
  480.         find    : CARDINAL;
  481.   BEGIN
  482.     key := line[0];
  483.     MagicStrings.Delete (line, 0, 1);
  484.     CASE key OF
  485.       'T' : ErrorWrite ('MausTausch-Version vom ');
  486.     | 'V' : ErrorWrite ('Boxversion: ');
  487.     | 'B' : ErrorWrite ('Boxtyp: ');
  488.     | 'I' : ErrorWrite ('Boxname: ');
  489.     | 'D' : ErrorWrite ('Tauschdatum: ');
  490.     | 'U' : ErrorWrite ('User: ');
  491.     | 'W' : ErrorWrite ('eingestellte Zeilenl„nge: ');
  492.     | 'L' : ErrorWrite ('eingestellte Seitenl„nge: ');
  493.     | 'C' : IF ~MagicStrings.Equal ('„”Ž™šž', line)
  494.             THEN
  495.               ErrorWrite ("Die in der Box eingestellten Umlaute entsprechen nicht den ST-Umlauten.");
  496.               ErrorLn();
  497.               ErrorWrite ("ST-Umlaute: „”Ž™šž");
  498.               ErrorLn();
  499.               ErrorWrite ("eingestellte Umlaute: ");
  500.             ELSE
  501.               ErrorWrite ('Umlaute: ');
  502.             END;
  503.     | 'S' : ErrorWrite ('Sortierung: '); (* Sortierung, interessiert uns nicht *) ;
  504.     ELSE
  505.       ErrorWrite (cUnknown);
  506.       ErrorWrite (key);
  507.     END;
  508.     ErrorWrite (line); ErrorLn();
  509.   END checkHeadLine;
  510.   
  511.   PROCEDURE processHead();
  512.     VAR head: mtTextfiles.TEXTFILE;
  513.   BEGIN
  514.     IF ~OpenTextFile(DataPath, HeadFile, mtTextfiles.READ, logFileBuffer, head) THEN
  515.       IF ~batchProcess
  516.       THEN
  517.         MTE.InfoAlert(MTE.noFile1, HeadFile, MTE.noFile4);
  518.       END;
  519.       RETURN;
  520.     END;
  521.     REPEAT
  522.       mtTextfiles.ReadLine(head, idScrap);
  523.       mtTextfiles.ReadLn(head);
  524.       checkHeadLine (idScrap);
  525.     UNTIL mtTextfiles.EndofText(head);
  526.     mtTextfiles.CloseTextfile (head);
  527.   END processHead;
  528.   
  529. BEGIN
  530.   anz := 0; 
  531.   not := 0;
  532.   anz2 := 0; 
  533.   not2 := 0;
  534.   refMess := FALSE; (* = Das bezieht sich noch auf die in scrap gespeicherte ID *)
  535.   writeInf:= FALSE;
  536.   errOpen := FALSE;
  537.   datOpen := FALSE;
  538.   abort   := FALSE;
  539.   refAssigned := FALSE;
  540.   v.bool := CatFiles.DeleteFile(DataPath, ErrFile);
  541.   (* #HEAD parsen, falls angekommen *)
  542.   IF headThere
  543.   THEN
  544.     processHead();
  545.   END;
  546.   IF ~OpenTextFile(DataPath, LogFile, mtTextfiles.READ, logFileBuffer, log) THEN
  547.     IF ~batchProcess
  548.     THEN
  549.       MTE.InfoAlert(MTE.noFile1, LogFile, MTE.noFile4);
  550.     END;
  551.     RETURN;
  552.   END;
  553.   readNew := TRUE;
  554.   REPEAT
  555.     IF readNew THEN
  556.       mtTextfiles.ReadChar(log, type);
  557.       mtTextfiles.ReadLine(log, idScrap);
  558.       mtTextfiles.ReadLn(log);
  559.     END;
  560.     readNew := TRUE;
  561.     CASE type OF
  562.       '!' : IF Strings.Pos ('Maximalgr”že berschritten', idScrap, 0) >= 0
  563.             THEN
  564.               (* Fehlermeldung rausbringen *)
  565.               maxOver := TRUE;
  566.               ErrorWrite ('Die MAUS meldet: ');
  567.               ErrorWrite (idScrap); ErrorLn();
  568.               refMess := FALSE;
  569.               refAssigned := FALSE;
  570.             END;
  571.             IF refMess & ~refAssigned THEN
  572.               IF (scrap[0] = 'G') &
  573.                  ((scrap[1] = '-') OR (scrap[1] = '+'))
  574.               THEN
  575.                 (* Gruppenbestellung akzeptiert von der Maus *)
  576.                 MagicStrings.Assign (scrap, mscrap);
  577.                 MagicStrings.Delete (mscrap, 0, 2);
  578.                 GroupSelect.ClearGroupChange (mscrap);
  579.               END;
  580.               ErrorWrite('Info zu Mitteilung ');
  581.               ErrorWrite(scrap); ErrorLn();
  582.               ErrorWrite(idScrap); ErrorLn();
  583.               IF refAssigned THEN refMess := FALSE END;
  584.             ELSE
  585.               IF refAssigned THEN refMess := FALSE END;
  586.             END;
  587.     | '#' : (* Modusende bzw. auch Modusanfang *)
  588.             refMess := FALSE;
  589.             IF idScrap[0] # 0C THEN
  590.               refMess := TRUE;
  591.               refAssigned := FALSE;
  592.               scrap := idScrap;
  593.             END;
  594.     | '%' : IF ~headThere
  595.             THEN
  596.               checkHeadLine (idScrap);
  597.             END;
  598.     | '=' : IF refMess THEN (* Nur dann sinnvoll *)
  599.               mscrap := scrap;
  600.               IF Messages.IsPrivateMessage (mscrap)
  601.               THEN
  602.                 MagicStrings.Assign (idScrap, shortId);
  603.                 (* N„chste Zeile lesen *)
  604.                 mtTextfiles.ReadChar(log, type);
  605.                 mtTextfiles.ReadLine(log, idScrap);
  606.                 mtTextfiles.ReadLn(log);
  607.                 IF (type = '!') & (idScrap [0] = '=')
  608.                 THEN
  609.                   (* wird wohl lange Id sein *)
  610.                   (* Gleichheitszeichen l”schen *)
  611.                   MagicStrings.Delete (idScrap, 0, 1);
  612.                 ELSE
  613.                   readNew := FALSE;
  614.                 END;
  615.                 v.bool := OpenPers();
  616.                 Messages.GetMsgFileName (scrap);
  617.                 InsertPersonal (shortId, idScrap, scrap);
  618.               END;
  619.               refAssigned := ~Messages.MsgHasCopys (scrap);
  620.               Messages.DeleteMessage (mscrap);
  621.               (* refAssigned := TRUE; *)
  622.             ELSE
  623.               ErrorWrite('Hier steht ein "=" in der Landschaft,'); ErrorLn();
  624.               ErrorWrite('das ich mir nicht erkl„ren kann : =');
  625.               ErrorWrite(idScrap); ErrorLn();
  626.             END;
  627.     | '?' : IF refMess THEN
  628.               (* :?Dupe zu #A1234@XY vom ... *)
  629.               IF Is (idScrap, isDupe) 
  630.               THEN
  631.                 ErrorWrite ('Maus meldet Dupe bei Mitteilung: ');
  632.                 ErrorWrite (scrap); ErrorLn();
  633.                 mscrap := scrap;
  634.                 IF Messages.IsPrivateMessage (mscrap) & 
  635.                    OpenPers()
  636.                 THEN
  637.                   (* Prfen, ob schon in Datenbank eingefgt *)
  638.                   find := MagicStrings.Pos ('#', idScrap, 0, FALSE);
  639.                   MagicStrings.Delete (idScrap, 0, find+1);
  640.                   find := MagicStrings.Pos (' ', idScrap, 0, FALSE);
  641.                   MagicStrings.Delete (idScrap, find, MagicStrings.Length (idScrap) - find);
  642.                   (* Jetzt steht in idScrap die ID von der Maus *)
  643.                   v.card := data.NumberOfID(dat, idScrap); 
  644.                   IF data.error = data.notFound
  645.                   THEN
  646.                     ErrorWrite ('Nachricht wird eingefgt');
  647.                     ErrorLn();
  648.                     Messages.GetMsgFileName (scrap);
  649.                     MagicStrings.Assign ("", shortId);
  650.                     InsertPersonal (idScrap, shortId, scrap);
  651.                   ELSE
  652.                     ErrorWrite ('Nachricht wird nicht eingefgt, ist schon da.');
  653.                     ErrorLn();
  654.                   END;
  655.                 ELSE
  656.                   ErrorWrite ('Nachricht ist ”ffentliche Nachricht, wird nicht eingefgt');
  657.                   ErrorLn();
  658.                 END;
  659.                 Messages.DeleteMessage (mscrap);
  660.               ELSIF Is (idScrap, refNotFound)
  661.               THEN
  662.                 (* ?Mitteilung "P17165@LU" nicht gefunden *)
  663.                 ErrorWrite ('Maus kennt Referenznachricht nicht bei Mitteilung: ');
  664.                 ErrorWrite (scrap); ErrorLn();
  665.                 (* Jetzt einfach dem Messagemanager sagen, er soll aus der 
  666.                  * Nachricht eine neue machen ohne Verkettung
  667.                  *)
  668.                 IF Messages.ChangeMessage (scrap)
  669.                 THEN 
  670.                   ErrorWrite ('Die Nachricht wird "Wildwest"-verkettet');
  671.                   ErrorLn();
  672.                 ELSE
  673.                   ErrorWrite ('Die Nachricht wird gel”scht');
  674.                   ErrorLn();
  675.                   Messages.DeleteMessage (scrap);
  676.                 END;
  677.               ELSE
  678.                 ErrorWrite('Maus meldet Fehler bei Mitteilung: ');
  679.                 ErrorWrite(scrap); ErrorLn();
  680.               END;
  681.               refAssigned := TRUE;
  682.             ELSE
  683.               ErrorWrite('Fehlermeldung der Maus: ');
  684.               ErrorWrite(idScrap);ErrorLn();
  685.             END;
  686.     | '"' : refMess := TRUE; scrap := idScrap; refAssigned := FALSE;
  687.             find := MagicStrings.Pos ('"', scrap, 0, FALSE);
  688.             IF find < LENGTH (scrap) THEN
  689.               (* zweites Anfhrungszeichen entfernen *)
  690.               MagicStrings.Delete (scrap, find, 1);
  691.             END;
  692.     | '$' : find := MagicStrings.Pos ('=', idScrap, 0, FALSE);
  693.             refMess := FALSE;
  694.             (* Kennung rauskopieren *)
  695.             IF find < (*SYSTEM.*)LENGTH(idScrap)
  696.             THEN
  697.               (* Gleichheitszeichen gefunden, Infofilenamen nach mscrap kopieren *)
  698.               MagicStrings.Copy (idScrap, 0, find, mscrap);
  699.               find2 := MagicStrings.Pos(' ', idScrap, find, FALSE);
  700.               IF find2 < (*SYSTEM.*)LENGTH(idScrap) THEN
  701.                 idScrap[find2] := 0C;
  702.                 MagicStrings.Copy(idScrap, find+1, find2-find-1, idScrap);
  703.                 IF ~writeInf THEN LoadInfoInf(FALSE, TRUE); writeInf := TRUE END;
  704.                 MagicStrings.Assign (idScrap, idScrap);
  705.                 SetInfoCrc(mscrap, idScrap);
  706.               END;
  707.             ELSE
  708.               (* M”glicherweise Jedesmal-Infofile *)
  709.               find := MagicStrings.Pos (' ', idScrap, 0, FALSE);
  710.               IF find < (*SYSTEM.*)LENGTH(idScrap)
  711.               THEN
  712.                 MagicStrings.Copy (idScrap, 0, find, mscrap);
  713.                 IF ~writeInf THEN LoadInfoInf(FALSE, TRUE); writeInf := TRUE END;
  714.                 MagicStrings.Assign ('0', idScrap);
  715.                 SetInfoCrc(mscrap, idScrap);
  716.               END;
  717.             END;
  718.             (*
  719.             IF isOneInf(idScrap, which, '=') THEN
  720.               find := MagicStrings.Pos(' ', idScrap, 0, FALSE);
  721.               IF find < LENGTH(idScrap) THEN
  722.                 idScrap[find] := 0C;
  723.                 MagicStrings.Copy(idScrap, 4, find-4, idScrap);
  724.                 IF ~writeInf THEN LoadInfoInf(FALSE, TRUE); writeInf := TRUE END;
  725.                 SetInfoCrc(which, idScrap);
  726.               END;
  727.             ELSE
  728.               ErrorWrite('Unbekanntes Infofile der Maus: ');
  729.               ErrorWrite(idScrap); ErrorLn();
  730.             END;
  731.             *)
  732.     | ELSE
  733.       ErrorWrite(cUnknown);
  734.       ErrorWrite(idScrap);
  735.       ErrorLn()
  736.     END;
  737.     gotId := (type = '=') & refMess;
  738.   UNTIL mtTextfiles.EndofText(log);
  739.   IF UserBLK.statusToIn & ~CatFiles.DeleteFile(MessagePath, CatTypes.statusInf) THEN
  740.     ErrorWrite(CatTypes.statusInf); ErrorWrite(notDeleted); ErrorLn();
  741.   END;
  742.   IF UserBLK.groupChangeToIn & ~CatFiles.DeleteFile(MessagePath, CatTypes.grSelect) THEN
  743.     ErrorWrite(CatTypes.grSelect); ErrorWrite(notDeleted); ErrorLn();
  744.   END;
  745.   v.bool := CatFiles.DeleteFile (MessagePath, CatTypes.userCmdFile);
  746.   CloseDat(abort, anz-not);
  747.   ErrorClose();
  748.   IF writeInf THEN SaveInfoInf(); END;
  749.   mtTextfiles.CloseTextfile(log);
  750.  
  751.   IF anz > 0 THEN (* Nur falls mind. eine versucht wurde zu schreiben *)
  752.     CatLog.putTime();
  753.     CatLog.WriteCard(anz-not);
  754.     CatLog.WriteString(' von ');
  755.     CatLog.WriteCard(anz);
  756.     CatLog.WriteKonjString (cMessStr,'',cExtStr, anz);
  757.     CatLog.WriteLine(cImpStr);
  758.     CatLog.WriteString(cSpace9Str);
  759.     CatLog.WriteCard(not);
  760.     CatLog.WriteKonjString (cMessStr,'',cExtStr,not);
  761.     CatLog.WriteLine(' wegen eines Fehlers oder vom Datenbankmodul abgelehnt');
  762.   END;
  763.  
  764. END processLog;
  765.  
  766. (*-------------------------------------------------------------------------*)
  767.  
  768. PROCEDURE OutfileOk(handle : INTEGER; VAR len : LONGCARD):BOOLEAN;
  769. (* Testet anhand einiger Kleinigkeiten, ob dies ein Outfile ist, nicht     *)
  770. (* 100% sicher, aber immerhin werden die ganz schlimmen F„lle damit        *)
  771. (* erkannt; Attention: may be critical if MAUS changes textfile-format!    *)
  772. VAR c : CHAR;
  773. BEGIN
  774.   len := MagicDOS.Fseek(0, handle, MagicDOS.SeekEnd);
  775.   v.lcard := MagicDOS.Fseek(0, handle, MagicDOS.SeekStart);
  776.   IF len < 6 THEN RETURN FALSE
  777.   ELSE
  778.     CatFiles.ReadFile(c, handle);
  779.     IF (c # '#') OR (CatFiles.FileError < 0) THEN RETURN FALSE END;
  780.     CatFiles.Seek(-5, handle, CatFiles.end);
  781.     CatFiles.ReadFile(c, handle);
  782.     IF (c # CR) OR (CatFiles.FileError < 0) THEN RETURN FALSE END;
  783.     CatFiles.ReadFile(c, handle);
  784.     IF (c # LF) OR (CatFiles.FileError < 0) THEN RETURN FALSE END;
  785.     CatFiles.ReadFile(c, handle);
  786.     IF (c # '#') OR (CatFiles.FileError < 0) THEN RETURN FALSE END;
  787.     CatFiles.ReadFile(c, handle);
  788.     IF (c # CR) OR (CatFiles.FileError < 0) THEN RETURN FALSE END;
  789.     CatFiles.ReadFile(c, handle);
  790.     IF (c # LF) OR (CatFiles.FileError < 0) THEN RETURN FALSE END;
  791.     RETURN TRUE
  792.   END
  793. END OutfileOk;
  794.  
  795. (*-------------------------------------------------------------------------*)
  796.  
  797. PROCEDURE OutfileVorbereiten(doDeArc, txtIsThere : BOOLEAN;
  798.                          VAR handle : INTEGER;
  799.                          VAR length : LONGCARD):BOOLEAN;
  800. (* Outfile fr das Einfgen vorbereiten, d.h. n”tigenfalls auspacken,      *)
  801. (* weiterhin ”ffnen und testen, ob es ok ist; Liefert direkt den Zugriffs- *)
  802. (* handle und L„nge, falls alles geklappt hat                              *)
  803. (* Diese Prozedur wird immer mit gesetztem WindUpdate aufgerufen, fr      *)
  804. (* l„ngere Aktionen sollte daher der Bildschirm freigegeben werden         *)
  805. VAR space    : LONGCARD;
  806.     disk     : MagicDOS.DISKINFO;
  807.     packret  : INTEGER;
  808. BEGIN
  809.   IF doDeArc THEN
  810.  
  811.     IF txtIsThere THEN
  812.       IF batchProcess OR (mtAlerts.Alert(1, MTE.outOverwrite) = 1) THEN
  813.         IF ~CatFiles.DeleteFile(ImportPath, OutfileTxt) THEN
  814.           CatFiles.ErrorAlert(MagicDOS.EAccDn);
  815.           CatLog.WriteLineNTime(cOfNdel);
  816.           CatLog.CloseLog();
  817.           RETURN FALSE
  818.         ELSE
  819.           CatLog.WriteLineNTime(cOfDel);
  820.         END
  821.       ELSE
  822.         CatLog.WriteLineNTime('Einfgen abgebrochen durch User');
  823.         CatLog.CloseLog();
  824.         RETURN FALSE
  825.       END
  826.     END;
  827.  
  828.     IF CatGlobal.multiTask THEN 
  829.       MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  830.     END;
  831.     CatLog.WriteLineNTime('Outfile auspacken');
  832.     ConfVars.GetConfDefBool (cRedirectToLog, v.bool, FALSE);
  833.     packret := ARCStarter.DeArc (v.bool);
  834.     IF CatGlobal.multiTask THEN 
  835.       MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  836.     END;
  837.     IF packret # 0 THEN
  838. (* Outfile auspacken, DeArc muž die Fehlermeldungen bringen!               *)
  839.       CatLog.putTime();
  840.       CatLog.WriteString('Fehler beim Auspacken, GEMDOS-Fehler Nr. ');
  841.       CatLog.WriteInt (packret);
  842.       CatLog.WriteLn;
  843.       MTE.warnAlert(~batchProcess, MTE.noDearc, '', '');
  844.       RETURN FALSE
  845.     ELSE
  846.       CatLog.WriteLineNTime('Outfile ausgepackt');
  847.       CatLog.WriteLn();
  848.     END;
  849.     (*
  850.     MagicAES.WindUpdate (MagicAES.ENDUPDATE); 
  851.     MagicAES.EvntTimer (200);
  852.     MagicAES.WindUpdate (MagicAES.BEGUPDATE); 
  853.     *)
  854.   ELSE
  855.     handle := CatFiles.OpenFile(ImportPath, OutfileTxt, CatFiles.readFile);
  856.     IF CatFiles.FileError = MagicDOS.EFilNF THEN (* File nicht gefunden?     *)
  857.       CatLog.WriteLineNTime('Outfile-Text nicht gefunden');
  858.       MTE.warnAlert(~batchProcess, MTE.outNotFound, '', '');
  859.       RETURN FALSE
  860.     END;
  861.     CatFiles.CloseFile(handle);
  862.   END;
  863.   
  864.   IF CatGlobal.multiTask THEN 
  865.     MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  866.   END;
  867.   (* Hier werden jetzt die IO-Filter aufgerufen *)
  868.   IF ~IoFilter.IoFilterOutfile()
  869.   THEN
  870.     IF CatGlobal.multiTask THEN 
  871.       MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  872.     END;
  873.     RETURN FALSE;
  874.   END;
  875.   Messages.ReReadMessageInfo();
  876.   IF CatGlobal.multiTask THEN 
  877.     MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  878.   END;
  879.  
  880.   handle := CatFiles.OpenFile(ImportPath, OutfileTxt, CatFiles.readFile);
  881. (* CloseFile durch OutfileOk!                                              *)
  882.  
  883.   IF CatFiles.FileError = MagicDOS.EFilNF THEN (* File nicht gefunden?     *)
  884.     CatLog.WriteLineNTime('Outfile-Text nicht gefunden');
  885.     MTE.warnAlert(~batchProcess, MTE.outNotFound, '', '');
  886.     RETURN FALSE
  887.   ELSIF CatFiles.FileError < 0 THEN (* allgemeiner Fehler *)
  888.     CatLog.WriteLineNTime('Dateifehler beim ™ffnen von Outfile-Text');
  889.     CatFiles.ErrorAlert(CatFiles.FileError);
  890.     RETURN FALSE
  891.   ELSIF ~OutfileOk(handle, length) THEN
  892. (* length enth„lt L„nge des Outfiles                                       *)
  893.     CatFiles.CloseFile(handle);
  894.     CatLog.WriteLineNTime('Defektes Outfile festgestellt');
  895.     MTE.warnAlert(~batchProcess, MTE.wrongOut, '', '');
  896.     RETURN FALSE
  897.   ELSE
  898. (* erst hier ist sicher, daž OUTFILE.TXT 'ok' ist, also OutfileOk passiert *)
  899. (* hat                                                                     *)
  900.  
  901.     CatLog.WriteLineNTime('Outfile ge”ffnet und getestet');
  902.     IF doDeArc & UserBLK.DeleteAfterDecode THEN
  903.       IF ~CatFiles.DeleteFile(ImportPath, archiveName) THEN
  904.         CatFiles.ErrorAlert(MagicDOS.EAccDn);
  905.         CatLog.WriteLineNTime('Fehler beim L”schen des Outfile-Archivs');
  906.       ELSE
  907.         CatLog.WriteLineNTime('Outfile-Archiv gel”scht nach auspacken');
  908.       END;
  909.     END;
  910.  
  911.     (* MagicDOS.Dfree(disk, ORD(CAP(DataPath[0])) - ORD('A') + 1); *)
  912.     CatGlobal.PathFree (disk, DataPath);
  913.     space := disk.bSecsiz * disk.bClsiz * disk.bFree;
  914.     IF space < length + secureBytes THEN
  915.       CatFiles.CloseFile(handle);
  916.       CatLog.WriteLineNTime('Zuwenig Diskplatz festgestellt');
  917.       MTE.warnAlert(~batchProcess, MTE.diskSpace, '', '');
  918.       RETURN FALSE
  919.     END
  920.   END;
  921.   RETURN TRUE;
  922. END OutfileVorbereiten;
  923.  
  924. (*------ Einlagern --------------------------------------------------------*)
  925.  
  926. PROCEDURE InitList(gPos   : onePosArrayPtr;
  927.                VAR gMax,
  928.                    gStart : oneMaxArray;
  929.                VAR maxPos : CARDINAL); (* initialisiert die Gruppenliste   *)
  930. VAR z : CARDINAL;
  931. BEGIN
  932.   maxPos := 0; (* n„chste zu belegende Position *)
  933.   FOR z := 0 TO maxGroup DO
  934.     gMax[z]   := EndOfList; (* Listenschw„nze *)
  935.     gStart[z] := EndOfList; (* Listenk”pfe *)
  936.   END;
  937.   FOR z := 0 TO maxArray DO
  938.     gPos^[z].next := EndOfList;
  939.   END;
  940.   groupsUsed := oneGroupSet{};
  941. END InitList;
  942.  
  943. PROCEDURE AppendToListNr(gPos  : onePosArrayPtr;  (* Positionsinformation  *)
  944.                      VAR gMax,                    (* Listenenden           *)
  945.                          gStart: oneMaxArray;     (* Listenk”pfe           *)
  946.                      VAR maxPos: CARDINAL;        (* max. Position in gPos *)
  947.                          count :  LONGCARD; nr    : CARDINAL);
  948. (* h„ngt die Msg, die bei <count> beginnt, an die Gruppenliste <nr> an *)
  949. BEGIN
  950.   INCL (groupsUsed, nr);
  951.   IF gStart[nr] = EndOfList THEN (* Noch keine Msg dieser Gruppe gefunden  *)
  952.     gStart[nr] := maxPos;        (* Dort kommt der erste Eintrag hin       *)
  953.   ELSE
  954.     WITH gPos^[gMax[nr]] DO      (* letztes belegtes Element dieser Gruppe *)
  955.       next   := maxPos;
  956.     END;
  957.   END;
  958.   gMax[nr] := maxPos;            (* n„chstes zu belegendes Arrayelement    *)
  959.   WITH gPos^[gMax[nr]] DO
  960.     next   := EndOfList;
  961.     offset := count;
  962.   END;
  963.   INC(maxPos);                   (* wieder n„chstes zu belegende Element   *)
  964. (* Ende erreicht, wenn maxPos > maxArray, muž unten in der Schleife        *)
  965. (* festgestellt werden                                                     *)
  966. END AppendToListNr;
  967.  
  968. PROCEDURE AppendToList(gPos   : onePosArrayPtr;
  969.                    VAR gMax,
  970.                        gStart : oneMaxArray;
  971.                    VAR maxPos : CARDINAL;
  972.                        count  : LONGCARD;
  973.                        gruppe : ARRAY OF CHAR):BOOLEAN;
  974. (* h„ngt die Msg, die bei <count> beginnt, an die entsprechende            *)
  975. (* Gruppenliste an. Sucht in der Namensliste der Gruppen nach dem String   *)
  976. (* <gruppe> <sonstige> werden auch sortiert, dazu wird die Liste erweitert *)
  977.  
  978. VAR z : CARDINAL; found : BOOLEAN;
  979. BEGIN
  980.   (*
  981.   MagicStrings.CAPS(gruppe);
  982.   *)
  983.   IF ~GroupSelect.GroupNumber(gruppe, z) & ~GroupSelect.AppendGroup(gruppe) THEN
  984.     RETURN FALSE
  985.   END;
  986.   AppendToListNr(gPos, gMax, gStart, maxPos, count, z);
  987.   RETURN TRUE
  988. END AppendToList;
  989.  
  990. (*------ Auslesen ---------------------------------------------------------*)
  991.  
  992. PROCEDURE ReadNextElement(gPos : onePosArrayPtr;
  993.                       VAR l    : LONGCARD;
  994.                       VAR next : CARDINAL):BOOLEAN;
  995. (* Wegen next nicht verwirren lassen, erst steht dort der Arrayindes       *)
  996. (* ("Pointer") der aktuellen Msg, anschliežend kommt der n„chste dort      *)
  997. (* hinein                                                                  *)
  998. BEGIN
  999.   next := gPos^[next].next;
  1000.   IF next = EndOfList THEN
  1001.     RETURN FALSE
  1002.   ELSE
  1003.     l := gPos^[next].offset;
  1004.     RETURN TRUE
  1005.   END;
  1006. END ReadNextElement;
  1007.  
  1008. (*--------- Sortierung ----------------------------------------------------*)
  1009.  
  1010. PROCEDURE ReadMemLine(VAR count : LONGCARD;
  1011.                       VAR str   : ARRAY OF CHAR;
  1012.                           oPtr  : CatTypes.LargeTextPtr;
  1013.                           oAnz  : LONGCARD);
  1014. (* liest eine Zeile aus dem Speicher bis zum CR/LF in <str> ein. CR wird   *)
  1015. (* durch ein 0C ersetzt und LF wird bersprungen                           *)
  1016. (*                                                                         *)
  1017. (* vor dem Aufruf muž mittels CheckMemLine und anschliežendem Test         *)
  1018. (* festgestellt worden sein, daž die Zeile auch komplett im Puffer ist     *)
  1019. VAR z : LONGCARD;
  1020. BEGIN
  1021.   (*
  1022.   z := 0;
  1023.   WHILE (z < LONG(HIGH(str))) & (oPtr^[count+z] # CR) DO
  1024.     str[SHORT(z)] := oPtr^[count+z];
  1025.     INC(z)
  1026.   END;
  1027.   str[SHORT(z)] := 0C;
  1028.   (* Die folgende Schleife erledigt auch das Problem, wenn die letzte        *)
  1029.   (* Schleife durch HIGH abgebrochen wurde                                   *)
  1030.   WHILE oPtr^[count+z] # LF DO
  1031.     INC(z)
  1032.   END;
  1033.   INC(count, z+1); (* +1 wg. n„chster zu bearbeitender Buchstabe     *)
  1034.   *)
  1035.   ASSEMBLER
  1036.     MOVE.L  count(A6),A0
  1037.     MOVE.L  (A0),D0         ; count nach D0, Adresse in A0
  1038.     MOVE.L  str(A6),A1      ; ADR(str) nach A1
  1039.     MOVE.W  str+4(A6),D1    ; High(Str) nach D1
  1040.     EXT.L   D1              ; auf Long expandieren
  1041.     MOVE.L  oPtr(A6),A2     ; oPtr nach A2
  1042.     MOVEQ   #0,D2           ; z auf 0
  1043.     ADDA.L  D0,A2           ; oPtr^[count+z] in A2
  1044.   loop:
  1045.     CMP.L   D2,D1           ; z < HIGH (str)
  1046.     BLT.S   endloop         ; z ist gr”žer gleich, branch
  1047.     CMPI.B  #CR,(A2)        ; oPtr^[count+z] # CR
  1048.     BEQ.S   endloop         ; ist CR, raus
  1049.     MOVE.B  (A2)+,(A1)+     ; str[z] := oPtr^[count+z];
  1050.     ADDQ.L  #1,D2
  1051.     BRA.S   loop
  1052.   endloop:
  1053.     MOVE.B  #0,(A1)         ; str[z] := 0c
  1054.   loop2:
  1055.     CMPI.B  #LF,(A2)+       ; oPtr^[count+z] # LF
  1056.     BEQ.S   endl2
  1057.     ADDQ.L  #1,D2           ; INC (z);
  1058.     BRA.S   loop2
  1059.   endl2:
  1060.     ADDQ.L  #1,D2           ; INC (count, z+1);
  1061.     ADD.L   D2,D0
  1062.     MOVE.L  D0,(A0)         ; count zurckschreiben
  1063.   END;
  1064.   (*
  1065.   CALLSYS (1, 4201, CADR ("ReadMemLine exit: Count: %ld"), count);
  1066.   *)
  1067. END ReadMemLine;
  1068.  
  1069. PROCEDURE CheckMemLine(VAR count : LONGCARD;
  1070.                            oPtr  : CatTypes.LargeTextPtr;
  1071.                            oAnz  : LONGCARD);
  1072. (* durchsucht den Speicher bis zum CR/LF                                   *)
  1073. BEGIN
  1074.   (*
  1075.   WHILE (count < oAnz) & (oPtr^[count] # LF) DO
  1076.     INC(count)
  1077.   END;
  1078.   (* jetzt entweder am Ende oder auf dem LF *)
  1079.   (* LF berspringen, fr den anderen Fall schadet es auch nicht             *)
  1080.   IF (count < oAnz)
  1081.   THEN
  1082.     INC(count);
  1083.   END;
  1084.   *)
  1085.   ASSEMBLER
  1086.     MOVE.L  count(A6),A0
  1087.     MOVE.L  (A0),D0     ; count
  1088.     MOVE.L  oAnz(A6),D1 ; oAnz
  1089.     MOVE.L  oPtr(A6),A1 ; Textadresse
  1090.     ADDA.L  D0,A1       ; oPtr^[count] in A1
  1091.  loop:
  1092.     CMP.L   D0,D1       ; count < oAnz
  1093.     BLE.S   endloop     ; count ist gr”žer
  1094.     CMPI.B  #LF,(A1)+   ; oPtr^[count] # LF
  1095.     BEQ.S   endloop
  1096.     ADDQ.L  #1,D0       ; INC (count)
  1097.     BRA.S   loop        ; und looping
  1098.  endloop:
  1099.     ADDQ.L  #1,D0       ; INC (count);
  1100.     MOVE.L  D0,(A0)     ; Variable zurckschreiben
  1101.   END;
  1102.   (*
  1103.   CALLSYS (1, 4201, CADR ("CheckMemLine exit: Count: %ld"), count);
  1104.   *)
  1105. (* LF berspringen, fr den anderen Fall schadet es auch nicht             *)
  1106. END CheckMemLine;
  1107.  
  1108. PROCEDURE HandleMessage(gPos   : onePosArrayPtr;
  1109.                     VAR gMax,
  1110.                         gStart : oneMaxArray;
  1111.                     VAR TxtOut : mtTextfiles.TEXTFILE;
  1112.                     VAR TxtOutOpen : BOOLEAN;
  1113.                     VAR TxtName: ARRAY OF CHAR;
  1114.                     VAR maxPos : CARDINAL;
  1115.                     VAR count  : LONGCARD;
  1116.                     VAR text   : CARDINAL;
  1117.                     VAR unknown: CARDINAL;
  1118.                         oPtr   : CatTypes.LargeTextPtr;
  1119.                         oAnz   : LONGCARD):BOOLEAN;
  1120. (* Geht zun„chst von <count> an aufw„rts durch, bis ein CR/LF/'G' od.      *)
  1121. (* ':','>','#' gefunden wird. Wenn ein 'G' gefunden wird, dann wird die    *)
  1122. (* Msg an die Liste fr die entsprechende Gruppe angeh„ngt.Falls die       *)
  1123. (* letzte Zeichenfolge nicht CR/LF/'#' war, dann wird bis zum Erreichen    *)
  1124. (* dieser Folge weitergesucht.                                             *)
  1125. (* <count> zeigt immer auf den n„chsten zu bearbeitenden Buchstaben        *)
  1126. (*                                                                         *)
  1127. (* Returniert FALSE, wenn eine Mitteilung abbricht und eine Speicher-      *)
  1128. (* verschiebung n”tig wird                                                 *)
  1129. (*                                                                         *)
  1130. (* Wenn TxtOutOpen TRUE ist dann muž noch eine Infodatei geschrieben       *)
  1131. (* werden; bis zu ihrem Ende                                               *)
  1132. VAR str,
  1133.     str2     : CatTypes.String1023;
  1134.     tmp      : LONGCARD;
  1135.     tmp2     : LONGCARD;
  1136.     old      : LONGCARD;
  1137.     isGroup  : BOOLEAN;
  1138.     ptr      : CatTypes.Str255Ptr;
  1139.     endLoop  : BOOLEAN;
  1140.     isInfo   : BOOLEAN;
  1141.     infLen   : INTEGER;
  1142.     strType  : NrTypes;
  1143.     i        : INTEGER;
  1144. BEGIN
  1145. (* Textfiles, d.h. Maus-Infofiles und das Logfile werden separat behandelt *)
  1146.  
  1147.   (* Ende der Zeile suchen, Index steht danach in tmp *)
  1148.   tmp := count;
  1149.   CheckMemLine (tmp, oPtr, oAnz);
  1150.   IF tmp >= oAnz
  1151.   THEN
  1152.     (*
  1153.     (* Zeile nicht mehr im Buffer, direkt wieder raus *)
  1154.     CatLog.WriteString ("Broken Id at beginnig of block");
  1155.     CatLog.WriteLn;
  1156.     *)
  1157.     
  1158.     DEC (count);
  1159.     RETURN FALSE;
  1160.   END;
  1161.  
  1162.   ptr := ADR(oPtr^[count]); (* Fr den Zugriff gleich *)
  1163.   isInfo := FALSE;
  1164.   IF ~TxtOutOpen THEN 
  1165.     strType := typeOf (ptr^); 
  1166.     isInfo := isOneInf (ptr^, infLen);
  1167.  
  1168.     (*
  1169.     i := 0;
  1170.     WHILE ((i< 255) & (ptr^[i] # CR)) DO
  1171.       str[i] := ptr^[i];
  1172.       INC(i);
  1173.     END;
  1174.     str[i] := '';
  1175.     CatLog.WriteString ("Handling Id: ");
  1176.     CatLog.WriteString (str);
  1177.     CatLog.WriteLn;
  1178.     *)
  1179.   END;
  1180.   IF TxtOutOpen        OR
  1181.      isInfo            OR
  1182.      isUnknownInf (ptr^, infLen)
  1183.      (*
  1184.      (strType = REN)   OR
  1185.      (strType = HEAD)  OR
  1186.      (strType = LOG)   OR
  1187.      *)
  1188.   THEN
  1189.  
  1190.     (* Hier wird sich auf die Reihenfolge der Abarbeitung verlassen        *)
  1191.     (* Wenn TxtOut # NIL, dann ist schon eine Textdatei offen und sie muž  *)
  1192.     (* noch auf die Platte geschrieben werden, da sie beim letzten Mal     *)
  1193.     (* nicht komplett im Puffer war.                                       *)
  1194.     (* !! Wenn ein Infotext abbricht, dann kann es nur am Ende sein        *)
  1195.  
  1196.     IF ~TxtOutOpen THEN (* Noch keine Datei offen, jetzt Namen erstellen   *)
  1197.       IF (strType = LOG) OR (strType = REN)
  1198.       THEN
  1199.         infLen := 3;
  1200.       ELSIF (strType = HEAD)
  1201.       THEN
  1202.         infLen := 4;
  1203.         headThere := TRUE;
  1204.       END;
  1205.       MagicStrings.Copy(ptr^, 0, infLen, str);
  1206.       IF ~isInfo & isUnknownInf (ptr^, infLen) 
  1207.        & ((strType = nottich) OR (strType = normal))
  1208.       THEN
  1209.         INC (unknown);
  1210.         CatLog.WriteLn();
  1211.         CatLog.WriteStringNTime ('Unbekannter Infotext im Outfile: ');
  1212.         CatLog.WriteString (str);
  1213.       END;
  1214.       MagicStrings.Assign (str, TxtName);
  1215.       MagicStrings.Append('.txt', str);
  1216.       MagicStrings.Assign (DataPath, str2);
  1217.       MagicStrings.Append (str, str2);
  1218.       IF ~(ConfVars.GetConfigBool (cNoInfoBackups, v.bool) & v.bool)
  1219.       THEN
  1220.         (* Nur beim ersten Mal ein Backup von #LOG anlegen! *)
  1221.         IF ((strType = LOG) & ~firstLog) OR
  1222.             (strType # LOG)
  1223.         THEN
  1224.           v.bool := CatGlobal.CreateBackup (str2);
  1225.         END;
  1226.       END;
  1227.       IF strType = LOG
  1228.       THEN
  1229.         TxtOutOpen := OpenTextFile(DataPath, str, mtTextfiles.APPEND,
  1230.                                    infoFileBuffer, TxtOut);
  1231.         IF ~TxtOutOpen
  1232.         THEN
  1233.           TxtOutOpen := OpenTextFile(DataPath, str, mtTextfiles.WRITE,
  1234.                                      infoFileBuffer, TxtOut);
  1235.         END;
  1236.         firstLog := TRUE;
  1237.       ELSE
  1238.         TxtOutOpen := OpenTextFile(DataPath, str, mtTextfiles.WRITE,
  1239.                                    infoFileBuffer, TxtOut);
  1240.       END;
  1241.       MTE.warnAlert(~TxtOutOpen, MTE.noFile1, str, MTE.noFile3);
  1242.       CheckMemLine(count, oPtr, oAnz); (* #LOG u.„. berspringen           *)
  1243.       INC(text); (* ein weiterer Text ist gekommen *)
  1244.     ELSE
  1245.       (* d.h. das Textfile ist schon offen, es liegt ein Wechsel des       *)
  1246.       (* Puffers vor, da beim alten das Ende berschritten wurde.          *)
  1247.     END;
  1248.     
  1249.     old := count; (* Mitz„hlen, fr die Anzeige unten *)
  1250.     
  1251.     (* Hier gilt folgendes: Wir sind entweder am Anfang des Infofiles
  1252.      * oder mittendrin. oPtr^[count] zeigt auf das erste Zeichen einer 
  1253.      * Zeile, d.h. auf einen ':' oder ein '#' (z.b. bei leeren Infofiles)
  1254.      * Wir kopieren nun zeilenweise alles in die Textdatei, count zeigt 
  1255.      * dabei *immer* auf den Anfang der Zeile!
  1256.      *)
  1257.     tmp := count;   (* tmp ist der tempor„re Z„hler. *)
  1258.     WHILE (oPtr^[count] # '#') & (tmp < oAnz) DO
  1259.       IF oPtr^[count] = ':'
  1260.       THEN
  1261.         INC (tmp);    (* ':' berspringen *)
  1262.       END;
  1263.       tmp2 := tmp;
  1264.       (* Ende der Zeile suchen, Index steht danach in tmp *)
  1265.       CheckMemLine (tmp, oPtr, oAnz);
  1266.       IF tmp < oAnz
  1267.       THEN
  1268.         (* Zeile ist noch im aktuellen Buffer, tmp zeigt aufs Ende, 
  1269.          * tmp2 auf Anfang! 
  1270.          *)
  1271.         ReadMemLine (tmp2, str, oPtr, oAnz);
  1272.         IF TxtOutOpen THEN (* Nur schreiben, wenn das ”ffnen geklappt hat    *)
  1273.           mtTextfiles.WriteLine(TxtOut, str);
  1274.           mtTextfiles.WriteLn(TxtOut);
  1275.         END;
  1276.         (* count auf Anfang der n„chsten Zeile zeigen lassen
  1277.          *)
  1278.         count := tmp2;
  1279.       END;
  1280.     END;
  1281.  
  1282.     (* Entweder sind wir am Ende des Infofiles oder der Buffer ist am Ende
  1283.      *)
  1284.     showImport.SetNew(count-old);
  1285.     CatGlobal.busyMouse();
  1286.     IF tmp >= oAnz THEN (* alle Zeichen im Puffer behandelt; kein Ende    *)
  1287.     (* Was muž man hier machen? Erstmal jedenfalls nichts                  *)
  1288.       RETURN FALSE; (* !!! Hier broken zurckgeben! *)
  1289.     ELSE
  1290.       INC(count); (* '#' berspringen                                      *)
  1291.       IF TxtOutOpen THEN
  1292.         mtTextfiles.CloseTextfile(TxtOut); (* Alles drin                   *)
  1293.         TxtOutOpen := FALSE; (* entwerten..                                *)
  1294.         (* Jetzt eventuell direkt parsen, falls n”tig *)
  1295.         TestDirectParse (TxtName);
  1296.         MagicStrings.Assign ('', TxtName);
  1297.       END;
  1298.     END;
  1299.   ELSE (* es ist eine Msg oder Statusmeldung                               *)
  1300.     isGroup := FALSE; (* kein 'G' gefunden                                 *)
  1301.     old     := count; (* jetzige Pos merken                                *)
  1302.     REPEAT
  1303.       REPEAT (* Mal alle Zeilen durchrappeln.. *)
  1304.         CheckMemLine(count, oPtr, oAnz)
  1305.       UNTIL (oPtr^[count] = 'G') OR (oPtr^[count] = '#') OR (count >= oAnz);
  1306.       (* ..bis zum Ende oder zur Gruppenangabe *)
  1307.       IF (oPtr^[count] = 'G') & (count < oAnz) THEN (* Gruppe gefunden? *)
  1308.         INC(count); (* 'G' berspringen *)
  1309.         ReadMemLine(count, str, oPtr, oAnz); (* dann mal lesen..           *)
  1310.         isGroup := TRUE;
  1311.       END;
  1312.     UNTIL (oPtr^[count] = '#') OR (count >= oAnz);
  1313.     (* Erstmal weitermachen bis zum Mitteilungsende                        *)
  1314.     IF count < oAnz THEN
  1315.       INC(count); (* '#' berspringen *)
  1316.       IF isGroup THEN
  1317. (*CatLog.WriteString('pos:');CatLog.WriteCard(count);CatLog.WriteLn(); *)
  1318.         RETURN AppendToList(gPos, gMax, gStart, maxPos, old, str);
  1319.         (* mal gucken, wo's hingeh”rt                                      *)
  1320.       ELSE (* Ist pers”nlich!                                              *)
  1321.         AppendToListNr(gPos, gMax, gStart, maxPos, old, dataSys.private);
  1322.       END;
  1323.     ELSE
  1324. (* Mitteilung bricht ab, Berechnung des zu verschiebenden Speichers        *)
  1325.       count := old-1; (* Sollte in jedem Fall auf den Anfang der ID zeigen *)
  1326. (*CatLog.WriteString('pos:');CatLog.WriteCard(count);CatLog.WriteLn(); *)
  1327.       RETURN FALSE
  1328.     END;
  1329.   END;
  1330. (*CatLog.WriteString('pos:');CatLog.WriteCard(count);CatLog.WriteLn(); *)
  1331.   RETURN TRUE
  1332. END HandleMessage;
  1333.  
  1334. (*--- Flagzeile prfen und Flags ggf. vorbesetzen ---------------------------*)
  1335.  
  1336. PROCEDURE CheckFlagLine (str: CatTypes.Str255Ptr; VAR bitWhishes : BITSET);
  1337. (*
  1338. Die Definition der Zeile im Outfile ist:
  1339.  
  1340. Krzel: s (Achtung, klein)
  1341.  
  1342. G   Gelesen (Nicht gelesen entspricht G-)
  1343. X   Totall”schung
  1344. F   Interessant (entspricht wohl fixieren bei anderen)
  1345. L   Gefiltert
  1346. V   Vererben
  1347. D   Teill”schung
  1348. K   Kommentieren
  1349. B   Beantworten
  1350. C   Echt gut (genauer: Userflag 1, Name frei konfigurierbar)
  1351. M   Echt Mist (genauer: Userflag 2, Name frei konfigurierbar)
  1352.  
  1353. G, X und F mssen, sofern vorhanden, am Anfang stehen.
  1354. ~~~
  1355. *)
  1356.  
  1357.   PROCEDURE CheckFlag (ch : CHAR; bit: INTEGER; VAR bits: BITSET);
  1358.   BEGIN
  1359.     IF ch = CAP(ch) THEN INCL (bits, bit);
  1360.     ELSE EXCL (bits, bit);
  1361.     END;
  1362.   END CheckFlag; 
  1363.   
  1364.   VAR idx: INTEGER;
  1365. BEGIN
  1366.   idx := 0;
  1367.   WHILE (idx < 254) & (ORD(str^[idx]) >= 32) DO
  1368.     CASE str^[idx] OF
  1369.       'B' : CheckFlag (str^[idx], dataSys.bAntworten, bitWhishes); |
  1370.       'C' : CheckFlag (str^[idx], dataSys.bUser1, bitWhishes); |
  1371.       'D' : CheckFlag (str^[idx], dataSys.bTeilloeschung, bitWhishes); |
  1372.       'F' : CheckFlag (str^[idx], dataSys.bInteressant, bitWhishes); |
  1373.       'G' : CheckFlag (str^[idx], dataSys.bGelesen, bitWhishes); |
  1374.       'K' : CheckFlag (str^[idx], dataSys.bKommentieren, bitWhishes); |
  1375.       'L' : CheckFlag (str^[idx], dataSys.bFiltered, bitWhishes); 
  1376.             IF (dataSys.bFiltered IN bitWhishes) & filteredToRead
  1377.             THEN
  1378.               INCL(bitWhishes, dataSys.bGelesen);
  1379.             END; |
  1380.       'M' : CheckFlag (str^[idx], dataSys.bUser2, bitWhishes); |
  1381.       'V' : CheckFlag (str^[idx], dataSys.bVererben, bitWhishes); |
  1382.       'X' : CheckFlag (str^[idx], dataSys.bTotalloeschung, bitWhishes); |
  1383.     ELSE
  1384.     END;
  1385.     INC (idx);
  1386.   END;
  1387. END CheckFlagLine;
  1388.  
  1389. (*--- Ausgabe ---------------------------------------------------------------*)
  1390.  
  1391. PROCEDURE HandleEvents ();
  1392. VAR z : CARDINAL;
  1393.     mBuff: ARRAY [0..15] OF INTEGER;
  1394.     dr   : RECORD
  1395.              CASE :BOOLEAN OF
  1396.                TRUE : x,y,w,h : INTEGER|
  1397.                FALSE: adr, dum: ADDRESS
  1398.              END
  1399.            END;
  1400.     event,
  1401.     evnt      : BITSET;
  1402.     doExit    : BOOLEAN;
  1403.     moX, moY  : INTEGER;
  1404.     moButton  : BITSET;
  1405.     kReturn   : INTEGER;
  1406.     moKState  : BITSET;
  1407.     bReturn   : INTEGER;
  1408.     scan      : INTEGER;
  1409.     sc,
  1410.     ch        : CHAR;
  1411.  
  1412. BEGIN
  1413.   IF CatGlobal.multiTask
  1414.   THEN
  1415.     (* Hier bei MultiTasking noch eine kleiner EventMulti und ein paar
  1416.      * Events verarbeiten 
  1417.      *)
  1418.     LOOP
  1419.       evnt := MagicAES.EvntMulti(
  1420.                  {MagicAES.MUMESAG, MagicAES.MUTIMER},
  1421.                   0,{},{}, 0,dr, 0, dr, mBuff, 0, 0,
  1422.                   moX, moY, moButton, kReturn, moKState, scan, ch, bReturn);
  1423.       (* Den Timerevent brauchen wir nicht *)
  1424.       event := evnt;
  1425.       doExit := evnt = BITSET{MagicAES.MUTIMER};
  1426.       EXCL (event, MagicAES.MUTIMER);
  1427.       doExit := event = BITSET{};
  1428.       sc := CHAR(SHORT(scan));
  1429.       v.bool := WdwManager.HandleEvent (evnt, mBuff, moButton, moKState, ch, sc, kReturn, moX, moY, bReturn);
  1430.       (* Jetzt die Kopie abfragen *)
  1431.       IF doExit THEN EXIT END;
  1432.     END;
  1433.   END;
  1434. END HandleEvents;
  1435.  
  1436. PROCEDURE WriteBufferedOutfile(oPtr : CatTypes.LargeTextPtr;
  1437.                               oAnz  : LONGCARD;
  1438.                               checkOwn : BOOLEAN;
  1439.                               ownName  : ARRAY OF CHAR;
  1440.                           REF gPos   : onePosArrayPtr;
  1441.                           REF gStart : oneMaxArray;
  1442.                           VAR gNot, gWatch, gAnz, gGarbage, gStatus, pmNot, gDupeCount : CARDINAL;
  1443.                           VAR USENETCHAIN, USENETOK : CARDINAL;
  1444.                           VAR abort  : BOOLEAN);
  1445. (* gibt nacheinander alle in der Gruppenliste gespeicherten Msg an data    *)
  1446. (* weiter (ber WriteMessage)                                              *)
  1447. (* Bricht bei Fehlermeldung von data ab                                    *)
  1448. (* Geht davon aus, daž die behandelte Msg komplett im Speicher steht,      *)
  1449. (* wovon man nach Kai's Doku bei der jetzigen Puffergr”že ausgehen darf    *)
  1450. VAR not, watch, anz, garbage, status, dupeCount : CARDINAL;
  1451.      (* Anzahl der Einfgeversuche/Ablehnungen/watchDogs/Fehlermails     *)
  1452.  
  1453.   PROCEDURE WriteOneGroup(gruppe : CARDINAL;
  1454.                           checkOwn : BOOLEAN;
  1455.                           ownName  : ARRAY OF CHAR; 
  1456.                       VAR not, watch, anz, garbage, status, dupeCount : CARDINAL;
  1457.                       VAR USENETCHAIN, USENETOK : CARDINAL;
  1458.                       VAR abort : BOOLEAN):BOOLEAN;
  1459.   (* gibt den Inhalt einer Gruppe aus *)
  1460.   VAR handle  : data.OneGroupHandle; (* Zugriffshandle fr die Datenbank   *)
  1461.  
  1462.     PROCEDURE WriteOneMsg(gruppe : CARDINAL; MessStart : LONGCARD; 
  1463.                           checkown : BOOLEAN; ownName : ARRAY OF CHAR;
  1464.                       VAR USENETCHAIN, USENETOK : CARDINAL;
  1465.                       VAR isDupe: BOOLEAN;
  1466.                       VAR abort : BOOLEAN):BOOLEAN;
  1467.     (* Gibt eine Gruppe aus; Rckgabewert ist, der Wert von MTDataBase     *)
  1468.     VAR count,
  1469.         old,
  1470.         start   : LONGCARD;
  1471.         toData  : data.PtrRecord;
  1472.         helpPtr : CatTypes.Str1023Ptr;
  1473.         what    : data.WhatsThat;
  1474.  
  1475.     PROCEDURE DeflectorShieldsStrongEnough(VAR mess : data.PtrRecord; what : data.WhatsThat; VAR bitWhishes : BITSET):BOOLEAN;
  1476.     (* Look, if the deflector-shields of CAT are hard enough to deflect incoming *)
  1477.     (* enemy message *)
  1478.     VAR DogsOpinion : Protokoll.watchType;
  1479.     BEGIN
  1480.       IF what # data.normal THEN RETURN FALSE END;
  1481.       (* user-aided external deflector-shield *)
  1482.       (* phasers locked on target *)
  1483.       IF mess.pGruppe # NIL THEN DEC(mess.pGruppe); END; (* Freundlichkeit fr WatchDog *)
  1484.       IF mess.pWegen # NIL  THEN DEC(mess.pWegen); END;  (* Freundlichkeit fr WatchDog *)
  1485.       IF mess.pVon # NIL    THEN DEC(mess.pVon); END;    (* Freundlichkeit fr WatchDog *)
  1486.       IF CatGlobal.multiTask THEN MagicAES.WindUpdate (MagicAES.BEGUPDATE); END;
  1487.       DogsOpinion := Protokoll.AcceptThis(mess);
  1488.       IF CatGlobal.multiTask THEN MagicAES.WindUpdate (MagicAES.ENDUPDATE); END;
  1489.       IF (DogsOpinion = Protokoll.pCatForget) OR (DogsOpinion = Protokoll.pCatFiltered) THEN
  1490.         CatLog.WriteStringNTime('Nachricht ');
  1491.         CatLog.WriteString(mess.pId^);
  1492.         IF DogsOpinion = Protokoll.pCatForget THEN 
  1493.           CatLog.WriteLine(' von WatchDog abgelehnt.');
  1494.           (* Scotty, energy *)
  1495.           RETURN TRUE; (* user-aided deflection succeded *)
  1496.         ELSIF DogsOpinion = Protokoll.pCatFiltered THEN
  1497.           CatLog.WriteLine(' vom WatchDog als gefiltert markiert');
  1498.           INCL(bitWhishes, dataSys.bFiltered);
  1499.           IF filteredToRead
  1500.           THEN
  1501.             INCL(bitWhishes, dataSys.bGelesen);
  1502.           END;
  1503.         END;
  1504.       END;
  1505.       IF mess.pGruppe # NIL THEN INC(mess.pGruppe); END; (* Freundlichkeit fr CAT *)
  1506.       IF mess.pWegen  # NIL THEN INC(mess.pWegen);  END; (* Freundlichkeit fr CAT *)
  1507.       IF mess.pVon    # NIL THEN INC(mess.pVon);    END; (* Freundlichkeit fr CAT *)
  1508.       RETURN FALSE;
  1509.       (* enemy Message entering .. *)
  1510.     END DeflectorShieldsStrongEnough;
  1511.     
  1512.     PROCEDURE AppendZero(start, next : LONGCARD);
  1513.     (* start : Startbyte der Zeile, next : Startbyte der n„chsten Zeile    *)
  1514.     (* In den gepufferten Text an passender Stelle ein Nullbyte schreiben  *)
  1515.     BEGIN
  1516.       IF next >= start + 2 THEN
  1517.         oPtr^[next-2] := 0C;
  1518.         (* Dort sollte das CR stehen, wenn nicht ist etwas schiefgelaufen  *)
  1519.       ELSE
  1520.         oPtr^[start] := 0C;
  1521.         (* Dann muž man wohl von einer leeren Zeile ausgehen               *)
  1522.       END;
  1523.     END AppendZero;
  1524.  
  1525.     PROCEDURE checkCopy(ptr : CatTypes.Str255Ptr):BOOLEAN;
  1526.     (* Stellt fest, ob es sich bei der bergebenen Msg um eine           *)
  1527.     (* kopierte oder weitergegebene Msg handelt.                         *)
  1528.     VAR saveChar : CHAR;
  1529.     BEGIN
  1530.       saveChar := ptr^[11]; ptr^[11] := 0C;
  1531.       IF MagicStrings.Equal('Kopiert von', ptr^) THEN
  1532.         ptr^[11] := saveChar;
  1533.         RETURN TRUE
  1534.       ELSE
  1535.         ptr^[11] := saveChar;
  1536.         saveChar := ptr^[17]; ptr^[17] := 0C;
  1537.         IF MagicStrings.Equal('Weitergegeben von', ptr^) THEN
  1538.           ptr^[17] := saveChar;
  1539.           RETURN TRUE
  1540.         ELSE
  1541.           ptr^[17] := saveChar;
  1542.           RETURN FALSE
  1543.         END;
  1544.       END;
  1545.     END checkCopy;
  1546.  
  1547. (*
  1548.     PROCEDURE prepareText (pText: ADDRESS; VAR count: LONGCARD; VAR TextMax: CARDINAL);
  1549.     BEGIN
  1550.       ASSEMBLER
  1551.         (* Die Routine k”nnte man prinzipiell durch eine Assemblerroutine ersetzen
  1552.          * Hier wird folgendes gemacht: Die Doppelpunkte am Anfang der Zeile 
  1553.          * werden entfernt, und CR/LFs werden durch einzelne LFs ersetzt
  1554.          * Das wird solange gemacht, bis entweder die maximale Messagel„nge
  1555.          * erreicht ist oder der Anfang der n„chsten Nachricht gefunden wurde
  1556.          *)
  1557.         MOVE.L  count(A6),A0   ; Z„hler nach D0
  1558.         MOVE.L  (A0),D0         
  1559.         MOVE.L  TextMax(A6),A0   ; TextMax nach D1
  1560.         MOVE.W  (A0),D1         
  1561.         EXT.L   D1
  1562.         MOVE.L  pText(A6),A0   ; Zeiger auf Text nach A0 (oPtr^[old])
  1563.         MOVE.L  A0,A1          ; Zeiger auf Text nach A1 (oPtr^[count])
  1564.         MOVEQ   #0,D2          ; Zwischenspeicher
  1565.         ADDQ.L  #1,D0
  1566.       outer_loop:
  1567.         ADDA.W  #1,A1          ; Adresse um eins erh”hen
  1568.       inner_loop:
  1569.         MOVE.B  (A1)+,D2       ; Zwischenspeichern 
  1570.         MOVE.B  D2,(A0)+       ; Byte umkopieren
  1571.         ADDQ.L  #1,D0
  1572.         ADDQ.L  #1,D1          ; TextMax erh”hen
  1573.         CMPI.L  #sixteenKB,D1
  1574.         BGE.S   end_outer
  1575.         CMPI.B  #CR,D2
  1576.         BEQ.S   end_inner
  1577.         CMPI.B  #0,D2
  1578.         BNE.S   inner_loop
  1579.       end_inner:  
  1580.         MOVE.B  #LF,-1(A0)      ; CR durch LF ersetzen 
  1581.         ADDA.W  #1,A1           ; LF berspringen
  1582.         MOVE.B  (A1),D2
  1583.         CMPI.B  #"#",D2
  1584.         BNE.S   outer_loop
  1585.       end_outer:
  1586.         MOVE.L  count(A6),A0   ; Z„hler nach A0
  1587.         MOVE.L  D0,(A0)        ; Variable zurckschreiben
  1588.         MOVE.L  TextMax(A6),A0 ; TextMax nach A0
  1589.         MOVE.W  D1,(A0)        ; Variable zurckschreiben
  1590.       END;
  1591.     END prepareText;
  1592. *)
  1593.  
  1594.     VAR isCopy : BOOLEAN; (* Gibt an, ob es sich bei der bearbeiteten Msg *)
  1595.                           (* um eine Kopie handelt. Dann wird der Header  *)
  1596.                           (* n„mlich doch mit in die Message gepackt      *)
  1597.         bitWhishes : BITSET; (* Hier werden die Flags bergeben, die direkt *)
  1598.                           (* beim Einfgen gesetzt werden sollen.           *)
  1599.         pFlagLine  : CatTypes.Str255Ptr; (* Pointer auf Zeile mit Flags     *)
  1600.  
  1601.         usenetChain, usenetOk : BOOLEAN;
  1602.         typeInfo              : BOOLEAN;
  1603.         tmpAdr                : ADDRESS;
  1604.         tmp                   : CatTypes.nameStrType;
  1605.     BEGIN
  1606.       bitWhishes := {};   (* Normalerweise h„tten wir gerne leere Bits *)
  1607.       typeInfo := FALSE;
  1608.       count := MessStart; (* MessStart zeigt auf den ersten char nach '#'  *)
  1609.       old   := count;
  1610.       start := old;       (* Fr die Fllstandsanzeige                     *)
  1611.       CheckMemLine(count, oPtr, oAnz); (* Zeile auslesen, MausNr           *)
  1612.       AppendZero(old, count);
  1613.       WITH toData DO
  1614.         pId := ADR(oPtr^[old]);
  1615.         (* Alles andere muž nicht kommen und wird erstmal auf null gesetzt *)
  1616.         whatsThere := data.stringSet{data.bId};
  1617.         pRefNr := NIL; pVon   := NIL; (* kommentierte Msg,    Absender    *)
  1618.         pAn    := NIL; pWegen := NIL; (* Empf„nger,           Betreff     *)
  1619.         pEZeit := NIL; pGruppe:= NIL; (* Eingabezeit,         Gruppe      *)
  1620.         pBSZeit:= NIL; pMId   := NIL; (* Bearb.status+Zeit,   MessageID   *)
  1621.         pRId   := NIL; pBox   := NIL; (* RId gem. Def.,       BoxInfo     *)
  1622.         pName  := NIL;                (* Name gem. Def falls # Absender   *)
  1623.         pGate  := NIL;                (* Gateway-Zeile                    *)
  1624.         pMime  := NIL;                (* MIME-Zeile                       *)
  1625.         pFollowupTo := NIL;           (* FollowupTo-Zeile                 *)
  1626.         pReplyTo    := NIL;           (* ReplyTo-Zeile                    *)
  1627.         pSender     := NIL;           (* Sender-Zeile                     *)
  1628.         pText  := NIL;                (* MsgText                          *)
  1629.         TextMax   := 0;
  1630.         pDistribution := NIL;
  1631.         isCopy := FALSE; (* Normalerweise handlet es sich nicht um eine Kopie *)
  1632.         (* Header abarbeiten *)
  1633.         REPEAT
  1634.           old := count;
  1635.           CheckMemLine(count, oPtr, oAnz);
  1636.           AppendZero(old, count);
  1637.           (* die folgende Adresse nur einmal berechnen, spart Code *)
  1638.           tmpAdr := ADR(oPtr^[old+1]);
  1639.           CASE oPtr^[old] OF
  1640.             '-' : pRefNr :=tmpAdr; INCL(whatsThere, data.bRefNr)|
  1641.             'V' : pVon   :=tmpAdr; INCL(whatsThere, data.bVon);
  1642.                   IF checkOwn THEN
  1643.                     IF MagicStrings.Equal(pVon^, ownName) THEN
  1644.                       INCL(bitWhishes, dataSys.bOwnMessage);
  1645.                     ELSE
  1646.                       MagicStrings.Copy (pVon^, 0, 6, tmp);
  1647.                       MagicStrings.CAPS (tmp);
  1648.                       IF MagicStrings.Pos (cSysop, tmp, 0, FALSE) = 0
  1649.                       THEN
  1650.                         (* Test auf eigene Nachricht als Sysop *)
  1651.                         IF MagicStrings.Pos (ownName, pVon^, LENGTH(cSysop), FALSE) < SIZE (pVon^)
  1652.                         THEN
  1653.                           INCL(bitWhishes, dataSys.bOwnMessage);
  1654.                         END;
  1655.                       END;
  1656.                     END;
  1657.                   END |
  1658.             'A' : pAn    :=tmpAdr; INCL(whatsThere, data.bAn)|
  1659.             'W' : pWegen :=tmpAdr; INCL(whatsThere, data.bWegen)|
  1660.             'E' : pEZeit :=tmpAdr; INCL(whatsThere, data.bEZeit)|
  1661.             'G' : pGruppe:=tmpAdr; INCL(whatsThere, data.bGruppe)|
  1662.             'B' : pBSZeit:=tmpAdr; INCL(whatsThere, data.bBSZeit)|
  1663.             'I' : pMId   :=tmpAdr; INCL(whatsThere, data.bMId)|
  1664.             'R' : pRId   :=tmpAdr; INCL(whatsThere, data.bRId)|
  1665.             'O' : pBox   :=tmpAdr; INCL(whatsThere, data.bBox)|
  1666.             'N' : pName  :=tmpAdr; INCL(whatsThere, data.bName)|
  1667.             'Y' : pGate  :=tmpAdr; INCL(whatsThere, data.bGate)|
  1668.             'M' : pMime  :=tmpAdr; INCL(whatsThere, data.bMime)|
  1669.             'F' : pFollowupTo  :=tmpAdr; INCL(whatsThere, data.bFollowupTo)|
  1670.             'T' : pReplyTo     :=tmpAdr; INCL(whatsThere, data.bReplyTo)|
  1671.             'D' : pDistribution := tmpAdr; INCL(whatsThere, data.bDistribution)|
  1672.             'S' : pSender      :=tmpAdr; INCL(whatsThere, data.bSender)|
  1673.             '>' : isCopy := checkCopy(tmpAdr); IF isCopy THEN count := old; END; |
  1674.             's' : pFlagLine := tmpAdr; CheckFlagLine (pFlagLine, bitWhishes); |
  1675.             '*' : (* Nachrichtentyp *) 
  1676.                   typeInfo := TRUE;
  1677.                   CASE oPtr^[old+1] OF
  1678.                     'A' : what := data.normal; |
  1679.                     'P' : what := data.personal; |
  1680.                     'S' : what := data.status; |
  1681.                   ELSE
  1682.                     typeInfo := FALSE; 
  1683.                   END;
  1684.                   |
  1685.           ELSE (* Sonst nichts machen *)
  1686.             helpPtr := ADR(oPtr^[old]);
  1687.             CatLog.WriteStringNTime('Unbekannte Zeilen-ID: ');
  1688.             CatLog.WriteLine(helpPtr^);
  1689.           END;
  1690.         UNTIL isCopy OR (oPtr^[count] IN CatTypes.charSet{(*'>',*) ':', '#'});
  1691.         (* Beginn des Headers, der Message oder Ende *)
  1692.   
  1693.         IF (oPtr^[count] # '#') THEN (* Dann kommt noch eine Nachricht *)
  1694.           pText := ADR(oPtr^[count]);
  1695.           INCL(whatsThere, data.bText);
  1696.           old := count;
  1697.           (* In prepareText wird genau das gleiche wie in der Routine unten
  1698.            * gemacht, nur in Assembler
  1699.            *)
  1700.            (*
  1701.           prepareText (pText, count, TextMax);
  1702.           *)
  1703.  
  1704.           REPEAT
  1705.             INC(count); (* Anfangsbuchstaben berspringen *)
  1706.             REPEAT (* eine Zeile lesen.. *)
  1707.               oPtr^[old] := oPtr^[count];
  1708.               INC(TextMax);
  1709.               INC(count);
  1710.               INC(old);
  1711.             UNTIL (TextMax >= sixteenKB) OR (oPtr^[old-1] IN CatTypes.charSet{CR, 0C}) OR (count >= oAnz);
  1712.             IF count < oAnz
  1713.             THEN
  1714.               (* ..bis zum CR                                                *)
  1715.               oPtr^[old-1] := LF; (* CR durch LF ersetzen                    *)
  1716.               INC(count);         (* LF berspringen                         *)
  1717.             END;
  1718.           UNTIL (oPtr^[count] = '#') OR (TextMax >= sixteenKB) OR (count >= oAnz);
  1719.           (* bis zum Ende dieser Msg oder 16k                              *)
  1720.         END;
  1721.       END; (* WITH toData DO *)
  1722.       IF (count < oAnz)
  1723.       THEN
  1724.         showImport.SetNew(count-start);
  1725.         CatGlobal.busyMouse(); 
  1726.         IF ~typeInfo 
  1727.         THEN
  1728.           what := data.PreCheck(toData);
  1729.         END;
  1730.         IF what = data.status THEN INC(status) END;
  1731.         IF what = data.garbage THEN
  1732.           INC(garbage);
  1733.           data.dumpMess(toData);
  1734.         ELSIF DeflectorShieldsStrongEnough(toData, what, bitWhishes) THEN
  1735.           INC(watch);
  1736.         ELSE
  1737.           (*
  1738.           IF useLongIds
  1739.           THEN
  1740.             WITH toData DO
  1741.               IF (data.bMId IN whatsThere)
  1742.               THEN
  1743.                 (* MId ist vorhanden, vertauschen mit normaler Id *)
  1744.                 tmpAdr := pId;
  1745.                 pId    := pMId;
  1746.                 pMId   := tmpAdr;
  1747.               END;
  1748.               IF (data.bRId IN whatsThere)
  1749.               THEN
  1750.                 IF (data.bRefNr IN whatsThere)
  1751.                 THEN
  1752.                   (* Vertauschen mit RId *)
  1753.                   tmpAdr := pRId;
  1754.                   pRId   := pRefNr;
  1755.                   pRefNr := tmpAdr;
  1756.                 ELSE
  1757.                   (* keine RefNr da, dann machen wir die RId zur RefNr
  1758.                    *)
  1759.                   pRefNr := pRId;
  1760.                   pRId   := NIL;
  1761.                   INCL (whatsThere, data.bRefNr);
  1762.                   EXCL (whatsThere, data.bRId);
  1763.                 END;
  1764.               END;
  1765.             END; (* IF useLongIds *)
  1766.           END;
  1767.           *)
  1768.           IF data.AppendMessage(handle, what, bitWhishes, toData, usenetChain, usenetOk, isDupe, abort) (* ACHTUNG, v.bool eigentlich ABORT! - > SOFORT ABBRECHEN *)
  1769.           THEN
  1770.             IF usenetChain THEN
  1771.               INC(USENETCHAIN);
  1772.               CatLog.WriteStringNTime("Usenetverkettung bei ");
  1773.               CatLog.WriteString(toData.pId^);
  1774.               IF usenetOk THEN
  1775.                 INC(USENETOK);
  1776.                 CatLog.WriteLine(" hergestellt.");
  1777.               ELSE
  1778.                 CatLog.WriteLine(" fehlgeschlagen.");
  1779.               END;
  1780.             END;
  1781.             RETURN TRUE;
  1782.           ELSE
  1783.             RETURN FALSE;
  1784.           END;
  1785.         END;
  1786.       ELSE 
  1787.         CatLog.WriteStringNTime ("Internal error in parser, crash avoided, message possibly lost");
  1788.       END;
  1789.       (* Message -> data *)
  1790.       RETURN TRUE; (* Nicht von der Datenbank abgelehnt *)
  1791.     END WriteOneMsg;
  1792.  
  1793.   VAR actualElem : CARDINAL; (* Aktueller MsgPointer im Array              *)
  1794.       groupScrap : CatTypes.String1023;
  1795.       isDupe     : BOOLEAN;
  1796.   BEGIN
  1797.     anz := 0; not := 0; watch := 0; garbage := 0; status := 0;
  1798.     dupeCount := 0;
  1799.     actualElem := gStart[gruppe];
  1800.     IF actualElem # EndOfList THEN
  1801.       CatLog.WriteLn();
  1802.       CatLog.WriteStringNTime(cGroupChange);
  1803.       IF gruppe = dataSys.private THEN
  1804.         CatLog.WriteLine(cPrivate);
  1805.       ELSIF gruppe <= maxGroup THEN
  1806.         GroupSelect.GroupName(gruppe, groupScrap);
  1807.         CatLog.WriteLine(groupScrap);
  1808.       ELSE
  1809.         CatLog.WriteLine('unknown');
  1810.       END;
  1811.  
  1812.       IF ~data.OpenOneGroup(gruppe, 1000, TRUE, handle) THEN
  1813.         CatLog.WriteLineNTime('™ffnen der Datenbank nicht m”glich');
  1814.         RETURN FALSE
  1815.       END;
  1816.  
  1817.        REPEAT
  1818.         IF ~WriteOneMsg(gruppe, gPos^[actualElem].offset, checkOwn, ownName, USENETCHAIN, USENETOK, isDupe, abort) THEN 
  1819.           IF isDupe
  1820.           THEN
  1821.             INC (dupeCount);
  1822.           END;
  1823.           INC(not); 
  1824.         END;
  1825.         INC(anz);
  1826.         IF anz MOD CARDINAL(redrawCheck) = 0 THEN HandleEvents(); END;
  1827.         actualElem := gPos^[actualElem].next;
  1828.       UNTIL (actualElem = EndOfList) OR abort;
  1829.  
  1830.       IF ~abort THEN
  1831.         data.CloseOneWriteGroup(handle, anz-not-watch-garbage-status, TRUE, abort);
  1832.       ELSE
  1833.         data.CloseOneWriteGroup(handle, anz-not-watch-garbage-status, FALSE, v.bool);
  1834.       END;
  1835.  
  1836.       CatLog.putTime();
  1837.       CatLog.WriteCard(anz-not-watch-garbage-status);
  1838.       CatLog.WriteString(' von ');
  1839.       CatLog.WriteCard(anz-status);
  1840.       CatLog.WriteKonjString (cMessStr,'',cExtStr, anz-status);
  1841.       CatLog.WriteLine(cImpStr);
  1842.       CatLog.WriteString('         ');
  1843.       CatLog.WriteCard(not);
  1844.       CatLog.WriteString(cDbStr);
  1845.       CatLog.WriteCard(watch);
  1846.       CatLog.WriteLine(cWdogStr);
  1847.       CatLog.WriteString(cSpace9Str);
  1848.       CatLog.WriteCard(garbage);
  1849.       CatLog.WriteKonjString (cMessStr,'',cExtStr, garbage);
  1850.       CatLog.WriteKonjString (cWarStr,'',cExtStr, garbage);
  1851.       CatLog.WriteLine(' fehlerhaft.');
  1852.       IF gruppe = dataSys.private THEN
  1853.         CatLog.WriteString(cSpace9Str);
  1854.         CatLog.WriteCard(status);
  1855.         CatLog.WriteKonjString (' Statusmeldung','','en', status);
  1856.         CatLog.WriteLine(cImpStr);
  1857.       END;
  1858.     END;
  1859.     RETURN ~abort
  1860.   END WriteOneGroup;
  1861.  
  1862. VAR z : CARDINAL;
  1863.     mBuff: ARRAY [0..15] OF INTEGER;
  1864.     dr   : RECORD
  1865.              CASE :BOOLEAN OF
  1866.                TRUE : x,y,w,h : INTEGER|
  1867.                FALSE: adr, dum: ADDRESS
  1868.              END
  1869.            END;
  1870.     event,
  1871.     evnt      : BITSET;
  1872.     doExit    : BOOLEAN;
  1873.     moX, moY  : INTEGER;
  1874.     moButton  : BITSET;
  1875.     kReturn   : INTEGER;
  1876.     moKState  : BITSET;
  1877.     bReturn   : INTEGER;
  1878.     scan      : INTEGER;
  1879.     sc,
  1880.     ch        : CHAR;
  1881. BEGIN
  1882.   FOR z := 0 TO maxGroup DO
  1883.     IF (z IN groupsUsed) THEN
  1884.       IF ~WriteOneGroup(z, checkOwn, ownName, not, watch, anz, garbage, status, dupeCount, USENETCHAIN, USENETOK, abort) THEN 
  1885.         RETURN
  1886.       ELSE
  1887.         INC(gNot, not); INC(gWatch, watch); INC(gAnz, anz); 
  1888.         INC(gGarbage, garbage); INC(gStatus, status); INC (gDupeCount, dupeCount);
  1889.         IF z = 0 THEN pmNot := not + garbage END; (* Anzahl der Fehler in PMs *)
  1890.       END;
  1891.       HandleEvents();
  1892.     END;
  1893.   END;
  1894. END WriteBufferedOutfile;
  1895.  
  1896. (*-------------------------------------------------------------------------*)
  1897.  
  1898. PROCEDURE HandleOutfileBuffer (gPos   : onePosArrayPtr;
  1899.                            VAR gMax,
  1900.                                gStart : oneMaxArray;
  1901.                            VAR TxtOut : mtTextfiles.TEXTFILE;
  1902.                            VAR TxtOutOpen : BOOLEAN;
  1903.                            VAR TxtName: ARRAY OF CHAR;
  1904.                            VAR maxPos : CARDINAL;
  1905.                                oPtr   : CatTypes.LargeTextPtr;
  1906.                                oAnz   : LONGCARD;
  1907.                            VAR count  : LONGCARD;
  1908.                                processed : LONGCARD;
  1909.                            VAR not, watch, anz, garbage, status, pmNot, dupeCount, text, unknown : CARDINAL;
  1910.                            VAR USENETCHAIN, USENETOK : CARDINAL;
  1911.                                checkOwn : BOOLEAN;
  1912.                                ownName  : ARRAY OF CHAR;
  1913.                            VAR abort  : BOOLEAN):BOOLEAN;
  1914. (* Durchsucht den angelegten Puffer, schreibt auftretende Textfiles        *)
  1915. (* in die entsprechenden Dateien und legt Listen mit den Anf„ngen der      *)
  1916. (* einzelnen Mitteilungen an                                               *)
  1917. (* Der Puffer wird bis oAnz durchsucht                                     *)
  1918. (* count gibt an, wo die Suche anfangen soll                               *)
  1919. (* normalerweise 1, damit das erste '#' bersprungen wird                  *)
  1920.  
  1921. VAR brokenMessage : BOOLEAN; (* Message auf Puffergrenze                   *)
  1922. BEGIN
  1923.   REPEAT
  1924.     InitList(gPos, gMax, gStart, maxPos);
  1925.     REPEAT
  1926.       brokenMessage := ~HandleMessage(gPos, gMax, gStart,
  1927.                         TxtOut, TxtOutOpen, TxtName, maxPos, count, text, unknown, oPtr, oAnz);
  1928. (* Dann wurde am Ende eine Msg durch die Puffergrenze getrennt -> kopieren *)
  1929. (* old enth„lt die Startposition der letzten Message                       *)
  1930.     UNTIL brokenMessage       OR
  1931.           (maxPos >= maxArray) OR   (* YYYY *)
  1932.           (count >= oAnz)      OR
  1933.           (oPtr^[count] = CR) & (oPtr^[count+1] = LF);
  1934.     WriteBufferedOutfile(oPtr, oAnz, checkOwn, ownName, gPos, gStart, 
  1935.                          not, watch, anz, garbage, status, pmNot, dupeCount,
  1936.                          USENETCHAIN, USENETOK,
  1937.                          abort);
  1938.   UNTIL brokenMessage  OR
  1939.         (count >= oAnz) OR
  1940.         (oPtr^[count] = CR) & (oPtr^[count+1] = LF) OR
  1941.         abort;
  1942.   RETURN brokenMessage
  1943. END HandleOutfileBuffer;
  1944.  
  1945. PROCEDURE OutfileEinsortieren():BOOLEAN;
  1946. VAR estMem     : LONGCARD; (* Vermutete n”tige Gr”že fr die Pufferung     *)
  1947.     isAvail    : LONGCARD; (* Vorhandener Speicher                         *)
  1948.     toAlloc    : LONGCARD; (* Berechnung des anzufordernden Speichers      *)
  1949.  
  1950.     scrap      : CatTypes.pathStrType;  (* Zugriffspfade erstellen         *)
  1951.  
  1952.     doDeArc    : BOOLEAN; (* Auspacken n”tig?                              *)
  1953.     convertOk  : BOOLEAN; (* hat da Einfgen bisher geklappt?              *)
  1954.     txtIsThere : BOOLEAN; (* Ist ein Outfile-Text schon vorhanden?         *)
  1955.  
  1956.     outHandle  : INTEGER; (* Handle des Outfiles                           *)
  1957.     outLength  : LONGCARD;(* L„nge des Outfiles                            *)
  1958.     processed  : LONGCARD;(* Wieviele Bytes wurden schon behandelt?        *)
  1959.  
  1960.     oAnz       : LONGCARD;(* Ende des Puffers bei oAnz                     *)
  1961.     oPtr       : CatTypes.LargeTextPtr; (* Zugriffpointer auf den Puffer   *)
  1962.  
  1963.     TxtOut     : mtTextfiles.TEXTFILE;
  1964.     TxtOutOpen : BOOLEAN;  (* Ist noch eine Datei offen?                   *)
  1965.     TxtName    : CatTypes.nameStrType;
  1966.     
  1967.     maxPos     : CARDINAL; (* N„chste zu belegende Stelle im PointerArray  *)
  1968.     count      : LONGCARD; (* Z„hlvariable fr die Behandlungsprozeduren   *)
  1969.     toRead     : LONGCARD; (* Berechnung der Anzahl zu lesender Bytes      *)
  1970.  
  1971.     abort      : BOOLEAN; (* Abbruch wegen Dateifehlers beim Schreiben auf *)
  1972.                           (* die Datenbank *)
  1973.     isWatch,
  1974.     WatchActive : BOOLEAN; (* WatchDog installiert und aktiv, nur fr Protokoll *)
  1975.  
  1976.     (* Fr die Statistik *)
  1977.     not, watch, anz, garbage, status, dupeCount, text, unknown : CARDINAL;
  1978.     gNot, gWatch, gAnz, gGarbage, gStatus, pmNot, gDupeCount, gText, gUnknown : CARDINAL;
  1979.     
  1980.     hasMxAlloc : BOOLEAN;
  1981.     
  1982.     (* Fr's Aufr„umen *)
  1983.     inMctrl    : BOOLEAN;
  1984.     infoWdwOpen: BOOLEAN;
  1985.  
  1986.     USENETCHAIN,
  1987.     USENETOK   : CARDINAL;
  1988.  
  1989.     checkOwn   : BOOLEAN;
  1990.     ownName    : CatTypes.String127;
  1991.     
  1992.   PROCEDURE cleanUp ();
  1993.   BEGIN
  1994.     CatLog.CloseLog();
  1995.     IF inMctrl THEN MagicAES.WindUpdate (MagicAES.ENDMCTRL); inMctrl := FALSE; END;
  1996.     IF CatGlobal.multiTask
  1997.     THEN
  1998.       (* MagicAES.WindUpdate wieder setzen und Menu wieder anschalten *)
  1999.       VDIStandards.enableOrDisableMenu (FALSE);
  2000.       MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  2001.     END;
  2002.     IF infoWdwOpen THEN showImport.Close(); END;
  2003.     mtAppl.MouseArrow();
  2004.   END cleanUp;    
  2005.  
  2006. BEGIN
  2007.   gNot := 0; gWatch := 0; gAnz := 0; gGarbage := 0; 
  2008.   gStatus := 0; pmNot := 0; gDupeCount := 0; gText := 0; gUnknown := 0;
  2009.   USENETCHAIN := 0; USENETOK := 0;
  2010.   maxOver := FALSE;
  2011.   firstLog := FALSE;
  2012.   headThere := FALSE;
  2013.   abort := FALSE;
  2014.   inMctrl := FALSE;
  2015.   infoWdwOpen := FALSE;
  2016.   IF ~CatLog.OpenLog() THEN
  2017.     MTE.info(MTE.noCatlog);
  2018.     RETURN FALSE;
  2019.   END;
  2020.   ConfVars.GetConfDefInt (cRedrawCheck, redrawCheck, 40);
  2021.   checkOwn := ConfVars.GetConfigString(cOwnName, ownName);
  2022.   IF checkOwn
  2023.   THEN
  2024.     MagicStrings.Assign (CatGlobal.userName, ownName);
  2025.   END;
  2026.   
  2027.   ConfVars.GetConfDefBool (cFilteredRead, filteredToRead, FALSE);
  2028.   (*
  2029.   ConfVars.GetConfDefBool (cUseLongIDs, useLongIds, FALSE);
  2030.   *)
  2031.  
  2032.   CatGlobal.busyMouse();
  2033.   IF CatGlobal.multiTask THEN 
  2034.     (* Bildschirm freigeben und alle Menus sperren 
  2035.      *)
  2036.     VDIStandards.enableOrDisableMenu (TRUE);
  2037.     MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  2038.   END;
  2039.   convertOk := FALSE;            (* bisher ist es schiefgelaufen :-)       *)
  2040.   doDeArc   := ARCName[0] # 0C;  (* auspacken, wenn Packer angemeldet      *)
  2041.   abort     := FALSE;
  2042.  
  2043.   IF handlePool.isOneGroupOpen() THEN
  2044.     CatLog.WriteLineNTime('Interner Fehler in der Lesehandleliste. Einfgen abgebrochen.');
  2045.     CatLog.CloseLog();
  2046.     MTE.info(MTE.groupsOpen);
  2047.     RETURN FALSE;
  2048.   END;
  2049.   
  2050.   MagicStrings.Assign(ImportPath, scrap);
  2051.   MagicStrings.Append(OutfileTxt, scrap);
  2052.   txtIsThere := CatFiles.Exists (scrap);  (* Outfile.txt da?                    *)
  2053.  
  2054.   MagicStrings.Assign(ImportPath, scrap);
  2055.   MagicStrings.Append(archiveName, scrap);
  2056.   IF doDeArc & ~CatFiles.Exists (scrap) THEN (* Ist das Outfile berhaupt da?   *)
  2057.     CatLog.WriteLineNTime('Outfile-Archiv nicht gefunden');
  2058.     IF ~batchProcess THEN
  2059.       IF CatGlobal.multiTask THEN 
  2060.         MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  2061.       END;
  2062.       MTE.info(MTE.noOutArc); (* Outfile nicht vorhanden !    *)
  2063.       IF txtIsThere THEN CatLog.WriteLineNTime('Outfile-Text ist vorhanden'); END;
  2064.       IF txtIsThere & (mtAlerts.Alert(1, MTE.doInsert) = 1) THEN
  2065.         doDeArc := FALSE; (* trotzdem einfgen! *)
  2066.         CatLog.WriteLineNTime('User best„tigt: Outfile-Text trotzdem einfgen.');
  2067.       ELSE
  2068.         IF txtIsThere THEN
  2069.           CatLog.WriteLineNTime('User lehnt einfgen vom Outfile-Text ab');
  2070.         END;
  2071.         (* Aufr„umen *)
  2072.         IF CatGlobal.multiTask THEN 
  2073.           MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  2074.         END;
  2075.         cleanUp();
  2076.         RETURN FALSE (* nicht da oder nicht gewollt *)
  2077.       END;
  2078.       IF CatGlobal.multiTask THEN 
  2079.         MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  2080.       END;
  2081.     ELSE
  2082.       CatLog.WriteLineNTime('Einfgen abgebrochen, da Batchbetrieb');
  2083.       cleanUp;
  2084.       RETURN FALSE
  2085.     END;
  2086.   END;
  2087.  
  2088.   IF CatGlobal.multiTask THEN 
  2089.     MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  2090.   END;
  2091.   IF ~OutfileVorbereiten(doDeArc, txtIsThere, outHandle, outLength) THEN
  2092.     IF CatGlobal.multiTask THEN 
  2093.       MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  2094.     END;
  2095.     cleanUp();
  2096.     RETURN FALSE
  2097.   END;
  2098.   IF CatGlobal.multiTask THEN 
  2099.     MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  2100.   END;
  2101.   
  2102.   (* Altes Logfile l”schen *)
  2103.   v.bool := CatFiles.DeleteFile (DataPath, LogFile);
  2104.   
  2105.   MagicAES.WindUpdate(MagicAES.BEGMCTRL); (* Prozežwechsel sperren *)
  2106.   inMctrl := TRUE;
  2107.  
  2108.   estMem := data.EstimateNecessaryMemory();
  2109.  
  2110.   CatLog.putTime();
  2111.   CatLog.WriteCard(outLength);
  2112.   CatLog.WriteLine(' Bytes Outfile L„nge. ');
  2113.   CatLog.putTime();
  2114.   CatLog.WriteCard(estMem);
  2115.   CatLog.WriteLine(' Bytes sch„tzt das Datenbankmodul als Speicherbedarf');
  2116.   
  2117. (* Schleife, da sich z.B. bei MiNT der freie Speicher zwischen fragen und  *)
  2118. (* Anforderung „ndern kann. Aus demselben Grund kann die Pufferung der     *)
  2119. (* Parameterdateien auch jetzt noch schiefgehen, aber ich weiž nicht, wie  *)
  2120. (* man das umgehen kann.                                                   *)
  2121.   hasMxAlloc := MagicDOS.Mxalloc ($FFFFFFFF,3) # ADDRESS(-32L);
  2122.   
  2123.   REPEAT
  2124.     CatLog.WriteLineNTime('Beginne Allozierungsschleife');
  2125.     isAvail  := MagicDOS.Malloc(LONG(-1)); (* Wieviel ist da?              *)
  2126.     (* isAvail := estMem + 37331;   (* YYYY wieder wegmachen *) *)
  2127.     (* isAvail := minSpace; *)
  2128.     CatLog.putTime();
  2129.     CatLog.WriteCard(isAvail);
  2130.     CatLog.WriteLine(' Bytes gr”žter Speicherblock');
  2131.     IF isAvail < minSpace THEN
  2132.       CatFiles.CloseFile(outHandle);
  2133.       CatLog.WriteLineNTime('Nicht genug Speicher frei fr das Einfgen');
  2134.       mtAppl.MouseArrow();
  2135.       MTE.noMemAlert();
  2136.       cleanUp();
  2137.       RETURN FALSE;
  2138.     ELSIF isAvail < estMem + minSpace THEN
  2139. (* Parameterdatei pažt vermutlich nicht rein, oder kein Platz mehr fr das *)
  2140. (* Outfile                                                                 *)
  2141.       (* Alert kommt nur, wenn nicht abgeschaltet *)
  2142.       ConfVars.GetConfDefBool (cBufferAlert, v.bool, TRUE);
  2143.       IF ~batchProcess & v.bool &
  2144.         (mtAlerts.Alert(2, MTE.noMemForBuffer) = 2)
  2145.       THEN
  2146.         CatFiles.CloseFile(outHandle);
  2147.         CatLog.WriteLineNTime('User lehnt Einfgen ab; Pufferspeicher zu klein');
  2148.         cleanUp;
  2149.         RETURN FALSE
  2150.       ELSE
  2151.         oAnz := BinOps.LowerLCard(minSpace, outLength);
  2152.         (* Nur das anfordern, was n”tig ist, aber h”chstens minSpace       *)
  2153.         CatLog.WriteStringNTime('Minimumspeicher: ');
  2154.       END;
  2155.     ELSIF isAvail < estMem + outLength THEN
  2156.       oAnz := isAvail-estMem; (* Anfordern, was m”glich ist                *)
  2157.       CatLog.WriteStringNTime('Teilpufferung: ');
  2158.     ELSE
  2159.       oAnz := outLength; (* Alles anfordern, Outfile pažt komplett         *)
  2160.       CatLog.WriteStringNTime('Vollpufferung: ');
  2161.     END;
  2162.     IF hasMxAlloc & (CatGlobal.multiTOS OR CatGlobal.magIx)
  2163.     THEN
  2164.       (* Alloziere Speicher readable und TT-RAM preferred *)
  2165.       oPtr := MagicDOS.Mxalloc(oAnz, $43);
  2166.     ELSE
  2167.       (* Normal allozieren *)
  2168.       oPtr := MagicDOS.Malloc(oAnz);
  2169.     END;
  2170.     CatLog.WriteCard(oAnz); CatLog.WriteLine(' Bytes angefordert');
  2171.  
  2172.   UNTIL oPtr # NIL; (* Wir machen den Spaž solange, bis es geklappt hat..  *)
  2173.   inMctrl := FALSE;
  2174.   MagicAES.WindUpdate(MagicAES.ENDMCTRL);(* Prozežwechsel wieder freigeben *)
  2175.  
  2176.   CatLog.WriteLineNTime('Ende der Allozierungsschleife, Speicher angefordert');
  2177.  
  2178.   CatLog.WriteLn();
  2179.   CatLog.WriteLineNTime('Beginn des Einfgens');
  2180.   Protokoll.isWatchDog(isWatch, WatchActive);
  2181.   CatLog.WriteLn();
  2182.   CatLog.WriteString('         ');
  2183.   IF isWatch THEN
  2184.    CatLog.WriteString('WatchDog installiert und ');
  2185.    IF ~WatchActive THEN CatLog.WriteString('nicht '); END;
  2186.    CatLog.WriteString('aktiv.');
  2187.   ELSE
  2188.     CatLog.WriteString('Kein WatchDog installiert.');
  2189.   END;
  2190.  
  2191.   showImport.Open(outLength);
  2192.  
  2193.   HandleEvents();
  2194.  
  2195.   infoWdwOpen := TRUE;
  2196.  
  2197.   data.PrepareToWrite();
  2198.   CatFiles.Seek(0, outHandle, CatFiles.start);
  2199.   processed := 0;     (* Bisher wurde nichts behandelt                     *)
  2200.   count     := 0;     (* Anzahl der Restbytes von der letzten Runde        *)
  2201.   TxtOutOpen:= FALSE; (* und auch keine Textdatei offen                    *)
  2202.   (* Achtung, hier wird count fr zwei verschiedene Funktionen gebraucht!  *)
  2203.   REPEAT
  2204.     not := 0; watch := 0; anz := 0; garbage := 0; status := 0; text := 0; unknown := 0; dupeCount := 0;
  2205. (*
  2206. CatLog.WriteString('--- Repeat-Schleife in Outfile-Einsortieren ---');CatLog.WriteLn();
  2207. CatLog.WriteString('processed:');CatLog.WriteCard(processed);CatLog.WriteLn();
  2208. CatLog.WriteString('count:');CatLog.WriteCard(count);CatLog.WriteLn();
  2209. *)
  2210.     toRead := BinOps.LowerLCard(oAnz-count, outLength-processed-count); (* -count neu! *)
  2211.     oAnz   := BinOps.LowerLCard(oAnz, outLength-processed); (* + count weg! *)
  2212.     (* Am Ende brauchen wir nicht mehr soviel und die Prozeduren oben      *)
  2213.     (* mssen das auch erfahren                                            *)
  2214.  
  2215.     CatFiles.ReadMuch(toRead, outHandle, ADR(oPtr^[count]));
  2216.     IF CatFiles.FileError < 0 THEN
  2217.       CatFiles.ErrorAlert(CatFiles.FileError);
  2218.       v.bool :=  MagicDOS.Mfree(oPtr);
  2219.       cleanUp();
  2220.       RETURN FALSE
  2221.     END;
  2222.     count := 1; (* Warum steht hier eine 1????? YYYY jetzt funktioniert's! *)
  2223. (*CatLog.WriteString('oAnz:');CatLog.WriteCard(oAnz);CatLog.WriteLn();*)
  2224.     IF HandleOutfileBuffer(ADR(g), m, s, (* vorl„ufig *)
  2225.                             TxtOut, TxtOutOpen, TxtName,
  2226.                             maxPos, oPtr, oAnz, count, processed, 
  2227.                             not, watch, anz, garbage, status, pmNot, dupeCount, text, unknown,
  2228.                             USENETCHAIN, USENETOK,
  2229.                             checkOwn, ownName,
  2230.                             abort) THEN
  2231.       INC(processed, count);
  2232.       (* Hier muž kopiert werden, da eine Msg auf der Puffergrenze steht   *)
  2233.       (* count steht auf der Startposition der getrennten Message          *)
  2234.       (* Den Block nach vorne schieben                                     *)
  2235.       Block.Copy(ADR(oPtr^[count]), oAnz-count, oPtr);
  2236.       count := oAnz-count; (* Anzahl der Restbytes                         *)
  2237.     ELSE
  2238.       count := 0; (* keine Restbytes                                       *)
  2239.       INC(processed, oAnz);
  2240.     END;
  2241. (*CatLog.WriteString('count:');CatLog.WriteCard(count);CatLog.WriteLn();*)
  2242.  
  2243.     INC(gNot, not); INC(gWatch, watch); INC(gAnz, anz); 
  2244.     INC(gGarbage, garbage); INC(gStatus, status); INC(gText, text);
  2245.     INC (gDupeCount, dupeCount); INC (gUnknown, unknown);
  2246.  
  2247.   UNTIL (processed >= outLength) OR abort; (* BIS ALLES DURCHGENUDELT IST *)
  2248.   CatFiles.CloseFile(outHandle); (* Hier ist ein Fehler tolerierbar        *)
  2249.   IF CatFiles.FileError < 0 THEN CatFiles.ErrorAlert(CatFiles.FileError) END;
  2250.  
  2251.   v.bool :=  MagicDOS.Mfree(oPtr); (* Vielleicht mal meckern..? *)
  2252.   
  2253.   IF ~abort & (gGarbage = 0) & (gNot - gDupeCount = 0) & UserBLK.DeleteAfterDecode THEN (* Soll gel”scht werden ?  *)
  2254.     IF ~CatFiles.DeleteFile(ImportPath, OutfileTxt) THEN
  2255.     (* OUTFILE.TXT l”schen..                                               *)
  2256.       CatFiles.ErrorAlert(CatFiles.FileError);
  2257.       CatLog.WriteLineNTime(cOfNdel);
  2258.     ELSE
  2259.       CatLog.WriteLineNTime(cOfDel);
  2260.     END
  2261.   ELSIF ~abort & UserBLK.DeleteAfterDecode
  2262.   THEN
  2263.     CatLog.WriteStringNTime('Outfile-Text nicht gel”scht, da ');
  2264.     IF gGarbage # 0
  2265.     THEN
  2266.       CatLog.WriteCard (gGarbage);
  2267.       CatLog.WriteKonjString (cMessStr,'',cExtStr, gGarbage);
  2268.       CatLog.WriteString (' kaputt ');
  2269.       IF (gNot - gDupeCount = 0)
  2270.       THEN
  2271.         CatLog.WriteKonjString (cWarStr,'.','en.', gGarbage);
  2272.         CatLog.WriteLn;
  2273.       ELSE
  2274.         CatLog.WriteString ('und ')
  2275.       END;
  2276.     END;
  2277.     IF (gNot - gDupeCount # 0)
  2278.     THEN
  2279.       CatLog.WriteCard (gNot - gDupeCount);
  2280.       CatLog.WriteKonjString (cMessStr,'',cExtStr, gNot - gDupeCount);
  2281.       CatLog.WriteString (' abgelehnt ');
  2282.       CatLog.WriteKonjString ('wurde','.','n.', gNot-gDupeCount);
  2283.       CatLog.WriteLn;
  2284.     END;
  2285.   END;
  2286.  
  2287.   IF ~abort THEN
  2288.     processLog();
  2289.  
  2290.     (* Hier werden jetzt die Filter nach dem Einfgen aufgerufen *)
  2291.     CatLog.WriteLn();
  2292.     v.bool := data.WritePos();
  2293.     IoFilter.IoFilterPastOutfile();
  2294.     v.bool := data.ReadPos();
  2295.     Messages.ReReadMessageInfo();
  2296.   END;
  2297.  
  2298.   CatLog.WriteLn();
  2299.   CatLog.putTime();
  2300.   CatLog.WriteLine('--- Gesamtstatistik ---');
  2301.   CatLog.WriteString(cSpace9Str);
  2302.   CatLog.WriteCard(gAnz-gNot-gWatch-gGarbage-gStatus);
  2303.   CatLog.WriteString(' von ');
  2304.   CatLog.WriteCard(gAnz-gStatus);
  2305.   CatLog.WriteKonjString (cMessStr,'',cExtStr, gAnz-gStatus);
  2306.   CatLog.WriteLine(cImpStr);
  2307.   CatLog.WriteString(cSpace9Str);
  2308.   CatLog.WriteCard(gNot);
  2309.   CatLog.WriteString(cDbStr);
  2310.   CatLog.WriteCard(gWatch);
  2311.   CatLog.WriteLine(cWdogStr);
  2312.   CatLog.WriteString(cSpace9Str);
  2313.   CatLog.WriteCard(gGarbage);
  2314.   CatLog.WriteKonjString (cMessStr,'',cExtStr, gGarbage);
  2315.   CatLog.WriteKonjString (cWarStr,'',cExtStr, gGarbage);
  2316.   CatLog.WriteLine(' fehlerhaft.');
  2317.   CatLog.WriteString(cSpace9Str);
  2318.   CatLog.WriteCard(gDupeCount);
  2319.   CatLog.WriteKonjString (cMessStr,'',cExtStr, gDupeCount);
  2320.   CatLog.WriteKonjString (cWarStr,' ein',cExtStr, gDupeCount);
  2321.   CatLog.WriteKonjString (' Dupe','','s', gDupeCount);
  2322.   CatLog.WriteLine('.');
  2323.   CatLog.WriteKonjString('         Es kam',' ','en ', gText);
  2324.   CatLog.WriteCard(gText);
  2325.   CatLog.WriteKonjString(' Maus-Infotext','','e', gText);
  2326.   CatLog.WriteLine('.');
  2327.   CatLog.WriteKonjString('         Es kam',' ','en ', gUnknown);
  2328.   CatLog.WriteCard(gUnknown);
  2329.   CatLog.WriteKonjString(' unbekannte', 'r', '', gUnknown);
  2330.   CatLog.WriteKonjString(' Infotext','','e', gUnknown);
  2331.   CatLog.WriteLine('.');
  2332.   CatLog.WriteString(cSpace9Str);
  2333.   CatLog.WriteCard(gStatus);
  2334.   CatLog.WriteKonjString(' Statusmeldung','','en', gStatus);
  2335.   CatLog.WriteLine (cImpStr);
  2336.  
  2337.   CatLog.WriteString('         ');
  2338.   CatLog.WriteCard(USENETCHAIN);
  2339.   CatLog.WriteKonjString(' Usenet-Verkettung','','en', USENETCHAIN);
  2340.   CatLog.WriteKonjString(' wurde','','n', USENETCHAIN);
  2341.   CatLog.WriteString(" gefunden, ");
  2342.   CatLog.WriteCard(USENETOK);
  2343.   CatLog.WriteKonjString(' konnte','','n', USENETOK);
  2344.   CatLog.WriteLine(" hergestellt werden.");
  2345.  
  2346.   CatLog.CloseLog();
  2347.  
  2348.   IF CatGlobal.multiTask
  2349.   THEN
  2350.     (* MagicAES.WindUpdate wieder setzen und Menu wieder anschalten *)
  2351.     VDIStandards.enableOrDisableMenu (FALSE);
  2352.     MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  2353.   END;
  2354.   showImport.Close();
  2355.   mtAppl.MouseArrow();
  2356.   v.bool := data.WritePos();
  2357.   
  2358.   IF ~batchProcess
  2359.   THEN
  2360.     MTE.warnAlert (pmNot # 0, MTE.pmDefect, '','');
  2361.     IF maxOver
  2362.     THEN
  2363.       v.int := mtAlerts.Alert (2, MTE.overSize);
  2364.       IF v.int = 1
  2365.       THEN
  2366.         CatHelp.DoHelp (CatHelp.oversize);
  2367.       END;
  2368.     END;
  2369.   END;
  2370.   Protokoll.SendPathUpdate (MessagePath);
  2371.   Protokoll.SendPathUpdate (DataPath);
  2372.  
  2373.   
  2374.   RETURN TRUE
  2375. END OutfileEinsortieren;
  2376.  
  2377. PROCEDURE EmergencyClose();
  2378. (* Schliežt die noch offene Protokolldatei im Falle eines Absturzes *)
  2379. (* Wird direkt in cat.m in den ExeptionHandler geh„ngt. *)
  2380. BEGIN
  2381.   CatLog.WriteLn();
  2382.   CatLog.WriteLine('### catlog.txt durch Traphandler geschlossen ###');
  2383.   CatLog.CloseLog();
  2384. END EmergencyClose;
  2385.  
  2386. END Parser. 
  2387.